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