1316485Sdavidcs/*
2316485Sdavidcs * Copyright (c) 2017-2018 Cavium, Inc.
3316485Sdavidcs * All rights reserved.
4316485Sdavidcs *
5316485Sdavidcs *  Redistribution and use in source and binary forms, with or without
6316485Sdavidcs *  modification, are permitted provided that the following conditions
7316485Sdavidcs *  are met:
8316485Sdavidcs *
9316485Sdavidcs *  1. Redistributions of source code must retain the above copyright
10316485Sdavidcs *     notice, this list of conditions and the following disclaimer.
11316485Sdavidcs *  2. Redistributions in binary form must reproduce the above copyright
12316485Sdavidcs *     notice, this list of conditions and the following disclaimer in the
13316485Sdavidcs *     documentation and/or other materials provided with the distribution.
14316485Sdavidcs *
15316485Sdavidcs *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16316485Sdavidcs *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17316485Sdavidcs *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18316485Sdavidcs *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19316485Sdavidcs *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20316485Sdavidcs *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21316485Sdavidcs *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22316485Sdavidcs *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23316485Sdavidcs *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24316485Sdavidcs *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25316485Sdavidcs *  POSSIBILITY OF SUCH DAMAGE.
26316485Sdavidcs *
27316485Sdavidcs * $FreeBSD: stable/11/sys/dev/qlnx/qlnxe/ecore_int_api.h 337517 2018-08-09 01:17:35Z davidcs $
28316485Sdavidcs *
29316485Sdavidcs */
30316485Sdavidcs
31316485Sdavidcs#ifndef __ECORE_INT_API_H__
32316485Sdavidcs#define __ECORE_INT_API_H__
33316485Sdavidcs
34320164Sdavidcs#include "common_hsi.h"
35320164Sdavidcs
36320164Sdavidcs#ifndef __EXTRACT__LINUX__
37316485Sdavidcs#define ECORE_SB_IDX		0x0002
38316485Sdavidcs
39316485Sdavidcs#define RX_PI		0
40316485Sdavidcs#define TX_PI(tc)	(RX_PI + 1 + tc)
41316485Sdavidcs
42316485Sdavidcs#ifndef ECORE_INT_MODE
43316485Sdavidcs#define ECORE_INT_MODE
44316485Sdavidcsenum ecore_int_mode {
45316485Sdavidcs	ECORE_INT_MODE_INTA,
46316485Sdavidcs	ECORE_INT_MODE_MSIX,
47316485Sdavidcs	ECORE_INT_MODE_MSI,
48316485Sdavidcs	ECORE_INT_MODE_POLL,
49316485Sdavidcs};
50316485Sdavidcs#endif
51316485Sdavidcs
52316485Sdavidcsstruct ecore_sb_info {
53320164Sdavidcs	struct status_block_e4 *sb_virt;
54316485Sdavidcs	dma_addr_t sb_phys;
55316485Sdavidcs	u32 sb_ack; /* Last given ack */
56316485Sdavidcs	u16 igu_sb_id;
57316485Sdavidcs	void OSAL_IOMEM *igu_addr;
58316485Sdavidcs	u8 flags;
59316485Sdavidcs#define ECORE_SB_INFO_INIT 	0x1
60316485Sdavidcs#define ECORE_SB_INFO_SETUP 	0x2
61316485Sdavidcs
62316485Sdavidcs#ifdef ECORE_CONFIG_DIRECT_HWFN
63316485Sdavidcs	struct ecore_hwfn *p_hwfn;
64316485Sdavidcs#endif
65316485Sdavidcs	struct ecore_dev *p_dev;
66316485Sdavidcs};
67316485Sdavidcs
68316485Sdavidcsstruct ecore_sb_info_dbg {
69316485Sdavidcs	u32 igu_prod;
70316485Sdavidcs	u32 igu_cons;
71320164Sdavidcs	u16 pi[PIS_PER_SB_E4];
72316485Sdavidcs};
73316485Sdavidcs
74316485Sdavidcsstruct ecore_sb_cnt_info {
75316485Sdavidcs	/* Original, current, and free SBs for PF */
76316485Sdavidcs	int orig;
77316485Sdavidcs	int cnt;
78316485Sdavidcs	int free_cnt;
79316485Sdavidcs
80316485Sdavidcs	/* Original, current and free SBS for child VFs */
81316485Sdavidcs	int iov_orig;
82316485Sdavidcs	int iov_cnt;
83316485Sdavidcs	int free_cnt_iov;
84316485Sdavidcs};
85316485Sdavidcs
86316485Sdavidcsstatic OSAL_INLINE u16 ecore_sb_update_sb_idx(struct ecore_sb_info *sb_info)
87316485Sdavidcs{
88316485Sdavidcs	u32 prod = 0;
89316485Sdavidcs	u16 rc   = 0;
90316485Sdavidcs
91316485Sdavidcs	// barrier(); /* status block is written to by the chip */
92316485Sdavidcs	// FIXME: need some sort of barrier.
93316485Sdavidcs	prod = OSAL_LE32_TO_CPU(sb_info->sb_virt->prod_index) &
94320164Sdavidcs	       STATUS_BLOCK_E4_PROD_INDEX_MASK;
95316485Sdavidcs	if (sb_info->sb_ack != prod) {
96316485Sdavidcs		sb_info->sb_ack = prod;
97316485Sdavidcs		rc |= ECORE_SB_IDX;
98316485Sdavidcs	}
99316485Sdavidcs
100316485Sdavidcs	OSAL_MMIOWB(sb_info->p_dev);
101316485Sdavidcs	return rc;
102316485Sdavidcs}
103316485Sdavidcs
104316485Sdavidcs/**
105316485Sdavidcs * @brief This function creates an update command for interrupts that is
106316485Sdavidcs *        written to the IGU.
107316485Sdavidcs *
108316485Sdavidcs * @param sb_info 	- This is the structure allocated and
109316485Sdavidcs *      	   initialized per status block. Assumption is
110316485Sdavidcs *      	   that it was initialized using ecore_sb_init
111316485Sdavidcs * @param int_cmd 	- Enable/Disable/Nop
112316485Sdavidcs * @param upd_flg 	- whether igu consumer should be
113316485Sdavidcs *      	   updated.
114316485Sdavidcs *
115316485Sdavidcs * @return OSAL_INLINE void
116316485Sdavidcs */
117316485Sdavidcsstatic OSAL_INLINE void ecore_sb_ack(struct ecore_sb_info *sb_info,
118316485Sdavidcs				     enum igu_int_cmd int_cmd, u8 upd_flg)
119316485Sdavidcs{
120316485Sdavidcs	struct igu_prod_cons_update igu_ack = { 0 };
121316485Sdavidcs
122337517Sdavidcs#ifndef ECORE_CONFIG_DIRECT_HWFN
123337517Sdavidcs	u32 val;
124337517Sdavidcs#endif
125337517Sdavidcs
126337517Sdavidcs#ifndef LINUX_REMOVE
127337517Sdavidcs	if (sb_info->p_dev->int_mode == ECORE_INT_MODE_POLL)
128337517Sdavidcs		return;
129337517Sdavidcs#endif
130316485Sdavidcs	igu_ack.sb_id_and_flags =
131337517Sdavidcs		 OSAL_CPU_TO_LE32((sb_info->sb_ack <<
132337517Sdavidcs		 IGU_PROD_CONS_UPDATE_SB_INDEX_SHIFT) |
133316485Sdavidcs		 (upd_flg << IGU_PROD_CONS_UPDATE_UPDATE_FLAG_SHIFT) |
134316485Sdavidcs		 (int_cmd << IGU_PROD_CONS_UPDATE_ENABLE_INT_SHIFT) |
135316485Sdavidcs		 (IGU_SEG_ACCESS_REG <<
136337517Sdavidcs		 IGU_PROD_CONS_UPDATE_SEGMENT_ACCESS_SHIFT));
137316485Sdavidcs
138316485Sdavidcs#ifdef ECORE_CONFIG_DIRECT_HWFN
139316485Sdavidcs	DIRECT_REG_WR(sb_info->p_hwfn, sb_info->igu_addr,
140316485Sdavidcs		      igu_ack.sb_id_and_flags);
141316485Sdavidcs#else
142337517Sdavidcs	val = OSAL_LE32_TO_CPU(igu_ack.sb_id_and_flags);
143337517Sdavidcs	DIRECT_REG_WR(OSAL_NULL, sb_info->igu_addr, val);
144316485Sdavidcs#endif
145316485Sdavidcs	/* Both segments (interrupts & acks) are written to same place address;
146316485Sdavidcs	 * Need to guarantee all commands will be received (in-order) by HW.
147316485Sdavidcs	 */
148316485Sdavidcs	OSAL_MMIOWB(sb_info->p_dev);
149316485Sdavidcs	OSAL_BARRIER(sb_info->p_dev);
150316485Sdavidcs}
151316485Sdavidcs
152316485Sdavidcs#ifdef ECORE_CONFIG_DIRECT_HWFN
153316485Sdavidcsstatic OSAL_INLINE void __internal_ram_wr(struct ecore_hwfn *p_hwfn,
154316485Sdavidcs					  void OSAL_IOMEM *addr,
155316485Sdavidcs					  int size, u32 *data)
156316485Sdavidcs#else
157316485Sdavidcsstatic OSAL_INLINE void __internal_ram_wr(void *p_hwfn,
158316485Sdavidcs					  void OSAL_IOMEM *addr,
159316485Sdavidcs					  int size, u32 *data)
160316485Sdavidcs
161316485Sdavidcs#endif
162316485Sdavidcs{
163316485Sdavidcs	unsigned int i;
164316485Sdavidcs
165316485Sdavidcs	for (i = 0; i < size / sizeof(*data); i++)
166316485Sdavidcs		DIRECT_REG_WR(p_hwfn, &((u32 OSAL_IOMEM *)addr)[i], data[i]);
167316485Sdavidcs}
168316485Sdavidcs
169316485Sdavidcs#ifdef ECORE_CONFIG_DIRECT_HWFN
170316485Sdavidcsstatic OSAL_INLINE void internal_ram_wr(struct ecore_hwfn *p_hwfn,
171316485Sdavidcs					void OSAL_IOMEM *addr,
172316485Sdavidcs					int size, u32 *data)
173316485Sdavidcs{
174316485Sdavidcs	__internal_ram_wr(p_hwfn, addr, size, data);
175316485Sdavidcs}
176316485Sdavidcs#else
177316485Sdavidcsstatic OSAL_INLINE void internal_ram_wr(void OSAL_IOMEM *addr,
178316485Sdavidcs					int size, u32 *data)
179316485Sdavidcs{
180316485Sdavidcs	__internal_ram_wr(OSAL_NULL, addr, size, data);
181316485Sdavidcs}
182316485Sdavidcs#endif
183320164Sdavidcs#endif
184316485Sdavidcs
185316485Sdavidcsstruct ecore_hwfn;
186316485Sdavidcsstruct ecore_ptt;
187316485Sdavidcs
188316485Sdavidcsenum ecore_coalescing_fsm {
189316485Sdavidcs	ECORE_COAL_RX_STATE_MACHINE,
190316485Sdavidcs	ECORE_COAL_TX_STATE_MACHINE
191316485Sdavidcs};
192316485Sdavidcs
193316485Sdavidcs/**
194316485Sdavidcs * @brief ecore_int_cau_conf_pi - configure cau for a given
195316485Sdavidcs *        status block
196316485Sdavidcs *
197316485Sdavidcs * @param p_hwfn
198316485Sdavidcs * @param p_ptt
199316485Sdavidcs * @param p_sb
200316485Sdavidcs * @param pi_index
201316485Sdavidcs * @param state
202316485Sdavidcs * @param timeset
203316485Sdavidcs */
204316485Sdavidcsvoid ecore_int_cau_conf_pi(struct ecore_hwfn		*p_hwfn,
205316485Sdavidcs			   struct ecore_ptt		*p_ptt,
206316485Sdavidcs			   struct ecore_sb_info		*p_sb,
207316485Sdavidcs			   u32				pi_index,
208316485Sdavidcs			   enum ecore_coalescing_fsm	coalescing_fsm,
209316485Sdavidcs			   u8				timeset);
210316485Sdavidcs
211316485Sdavidcs/**
212316485Sdavidcs * @brief ecore_int_igu_enable_int - enable device interrupts
213316485Sdavidcs *
214316485Sdavidcs * @param p_hwfn
215316485Sdavidcs * @param p_ptt
216316485Sdavidcs * @param int_mode - interrupt mode to use
217316485Sdavidcs */
218316485Sdavidcsvoid ecore_int_igu_enable_int(struct ecore_hwfn *p_hwfn,
219316485Sdavidcs			      struct ecore_ptt *p_ptt,
220316485Sdavidcs			      enum ecore_int_mode int_mode);
221316485Sdavidcs
222316485Sdavidcs/**
223316485Sdavidcs * @brief ecore_int_igu_disable_int - disable device interrupts
224316485Sdavidcs *
225316485Sdavidcs * @param p_hwfn
226316485Sdavidcs * @param p_ptt
227316485Sdavidcs */
228316485Sdavidcsvoid ecore_int_igu_disable_int(struct ecore_hwfn *p_hwfn,
229316485Sdavidcs			       struct ecore_ptt	*p_ptt);
230316485Sdavidcs
231316485Sdavidcs/**
232316485Sdavidcs * @brief ecore_int_igu_read_sisr_reg - Reads the single isr multiple dpc
233316485Sdavidcs *        register from igu.
234316485Sdavidcs *
235316485Sdavidcs * @param p_hwfn
236316485Sdavidcs *
237316485Sdavidcs * @return u64
238316485Sdavidcs */
239316485Sdavidcsu64 ecore_int_igu_read_sisr_reg(struct ecore_hwfn *p_hwfn);
240316485Sdavidcs
241316485Sdavidcs#define ECORE_SP_SB_ID 0xffff
242316485Sdavidcs
243316485Sdavidcs/**
244316485Sdavidcs * @brief ecore_int_sb_init - Initializes the sb_info structure.
245316485Sdavidcs *
246316485Sdavidcs * once the structure is initialized it can be passed to sb related functions.
247316485Sdavidcs *
248316485Sdavidcs * @param p_hwfn
249316485Sdavidcs * @param p_ptt
250316485Sdavidcs * @param sb_info	points to an uninitialized (but
251316485Sdavidcs *			allocated) sb_info structure
252316485Sdavidcs * @param sb_virt_addr
253316485Sdavidcs * @param sb_phy_addr
254316485Sdavidcs * @param sb_id		the sb_id to be used (zero based in driver)
255316485Sdavidcs *			should use ECORE_SP_SB_ID for SP Status block
256316485Sdavidcs *
257316485Sdavidcs * @return enum _ecore_status_t
258316485Sdavidcs */
259316485Sdavidcsenum _ecore_status_t ecore_int_sb_init(struct ecore_hwfn	*p_hwfn,
260316485Sdavidcs				       struct ecore_ptt		*p_ptt,
261316485Sdavidcs				       struct ecore_sb_info	*sb_info,
262316485Sdavidcs				       void			*sb_virt_addr,
263316485Sdavidcs				       dma_addr_t		sb_phy_addr,
264316485Sdavidcs				       u16			sb_id);
265316485Sdavidcs/**
266316485Sdavidcs * @brief ecore_int_sb_setup - Setup the sb.
267316485Sdavidcs *
268316485Sdavidcs * @param p_hwfn
269316485Sdavidcs * @param p_ptt
270316485Sdavidcs * @param sb_info	initialized sb_info structure
271316485Sdavidcs */
272316485Sdavidcsvoid ecore_int_sb_setup(
273316485Sdavidcs		struct ecore_hwfn	*p_hwfn,
274316485Sdavidcs		struct ecore_ptt		*p_ptt,
275316485Sdavidcs		struct ecore_sb_info	*sb_info);
276316485Sdavidcs
277316485Sdavidcs/**
278316485Sdavidcs * @brief ecore_int_sb_release - releases the sb_info structure.
279316485Sdavidcs *
280316485Sdavidcs * once the structure is released, it's memory can be freed
281316485Sdavidcs *
282316485Sdavidcs * @param p_hwfn
283316485Sdavidcs * @param sb_info	points to an allocated sb_info structure
284316485Sdavidcs * @param sb_id		the sb_id to be used (zero based in driver)
285316485Sdavidcs *			should never be equal to ECORE_SP_SB_ID
286316485Sdavidcs *			(SP Status block)
287316485Sdavidcs *
288316485Sdavidcs * @return enum _ecore_status_t
289316485Sdavidcs */
290316485Sdavidcsenum _ecore_status_t ecore_int_sb_release(struct ecore_hwfn	*p_hwfn,
291316485Sdavidcs					  struct ecore_sb_info	*sb_info,
292316485Sdavidcs					  u16			sb_id);
293316485Sdavidcs
294316485Sdavidcs/**
295316485Sdavidcs * @brief ecore_int_sp_dpc - To be called when an interrupt is received on the
296316485Sdavidcs *        default status block.
297316485Sdavidcs *
298316485Sdavidcs * @param p_hwfn - pointer to hwfn
299316485Sdavidcs *
300316485Sdavidcs */
301316485Sdavidcsvoid ecore_int_sp_dpc(osal_int_ptr_t hwfn_cookie);
302316485Sdavidcs
303316485Sdavidcs/**
304316485Sdavidcs * @brief ecore_int_get_num_sbs - get the number of status
305316485Sdavidcs *        blocks configured for this funciton in the igu.
306316485Sdavidcs *
307316485Sdavidcs * @param p_hwfn
308316485Sdavidcs * @param p_sb_cnt_info
309316485Sdavidcs *
310316485Sdavidcs * @return
311316485Sdavidcs */
312316485Sdavidcsvoid ecore_int_get_num_sbs(struct ecore_hwfn	    *p_hwfn,
313316485Sdavidcs			   struct ecore_sb_cnt_info *p_sb_cnt_info);
314316485Sdavidcs
315316485Sdavidcs/**
316316485Sdavidcs * @brief ecore_int_disable_post_isr_release - performs the cleanup post ISR
317316485Sdavidcs *        release. The API need to be called after releasing all slowpath IRQs
318316485Sdavidcs *        of the device.
319316485Sdavidcs *
320316485Sdavidcs * @param p_dev
321316485Sdavidcs *
322316485Sdavidcs */
323316485Sdavidcsvoid ecore_int_disable_post_isr_release(struct ecore_dev *p_dev);
324316485Sdavidcs
325316485Sdavidcs/**
326316485Sdavidcs * @brief ecore_int_attn_clr_enable - sets whether the general behavior is
327316485Sdavidcs *        preventing attentions from being reasserted, or following the
328316485Sdavidcs *        attributes of the specific attention.
329316485Sdavidcs *
330316485Sdavidcs * @param p_dev
331316485Sdavidcs * @param clr_enable
332316485Sdavidcs *
333316485Sdavidcs */
334316485Sdavidcsvoid ecore_int_attn_clr_enable(struct ecore_dev *p_dev, bool clr_enable);
335316485Sdavidcs
336316485Sdavidcs/**
337316485Sdavidcs * @brief Read debug information regarding a given SB.
338316485Sdavidcs *
339316485Sdavidcs * @param p_hwfn
340316485Sdavidcs * @param p_ptt
341316485Sdavidcs * @param p_sb - point to Status block for which we want to get info.
342316485Sdavidcs * @param p_info - pointer to struct to fill with information regarding SB.
343316485Sdavidcs *
344316485Sdavidcs * @return ECORE_SUCCESS if pointer is filled; failure otherwise.
345316485Sdavidcs */
346316485Sdavidcsenum _ecore_status_t ecore_int_get_sb_dbg(struct ecore_hwfn *p_hwfn,
347316485Sdavidcs					  struct ecore_ptt *p_ptt,
348316485Sdavidcs					  struct ecore_sb_info *p_sb,
349316485Sdavidcs					  struct ecore_sb_info_dbg *p_info);
350316485Sdavidcs
351316485Sdavidcs/**
352316485Sdavidcs * @brief - Move a free Status block between PF and child VF
353316485Sdavidcs *
354316485Sdavidcs * @param p_hwfn
355316485Sdavidcs * @param p_ptt
356316485Sdavidcs * @param sb_id - The PF fastpath vector to be moved [re-assigned if claiming
357316485Sdavidcs *                from VF, given-up if moving to VF]
358316485Sdavidcs * @param b_to_vf - PF->VF == true, VF->PF == false
359316485Sdavidcs *
360316485Sdavidcs * @return ECORE_SUCCESS if SB successfully moved.
361316485Sdavidcs */
362316485Sdavidcsenum _ecore_status_t
363316485Sdavidcsecore_int_igu_relocate_sb(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
364316485Sdavidcs			  u16 sb_id, bool b_to_vf);
365316485Sdavidcs#endif
366