1fe56b9e6SYuval Mintz /* QLogic qed NIC Driver 2fe56b9e6SYuval Mintz * Copyright (c) 2015 QLogic Corporation 3fe56b9e6SYuval Mintz * 4fe56b9e6SYuval Mintz * This software is available under the terms of the GNU General Public License 5fe56b9e6SYuval Mintz * (GPL) Version 2, available from the file COPYING in the main directory of 6fe56b9e6SYuval Mintz * this source tree. 7fe56b9e6SYuval Mintz */ 8fe56b9e6SYuval Mintz 9fe56b9e6SYuval Mintz #include <linux/types.h> 10fe56b9e6SYuval Mintz #include <asm/byteorder.h> 11fe56b9e6SYuval Mintz #include <linux/io.h> 12fe56b9e6SYuval Mintz #include <linux/bitops.h> 13fe56b9e6SYuval Mintz #include <linux/delay.h> 14fe56b9e6SYuval Mintz #include <linux/dma-mapping.h> 15fe56b9e6SYuval Mintz #include <linux/errno.h> 16fe56b9e6SYuval Mintz #include <linux/interrupt.h> 17fe56b9e6SYuval Mintz #include <linux/kernel.h> 18fe56b9e6SYuval Mintz #include <linux/pci.h> 19fe56b9e6SYuval Mintz #include <linux/slab.h> 20fe56b9e6SYuval Mintz #include <linux/string.h> 21fe56b9e6SYuval Mintz #include "qed.h" 22fe56b9e6SYuval Mintz #include "qed_hsi.h" 23fe56b9e6SYuval Mintz #include "qed_hw.h" 24fe56b9e6SYuval Mintz #include "qed_init_ops.h" 25fe56b9e6SYuval Mintz #include "qed_int.h" 26fe56b9e6SYuval Mintz #include "qed_mcp.h" 27fe56b9e6SYuval Mintz #include "qed_reg_addr.h" 28fe56b9e6SYuval Mintz #include "qed_sp.h" 29fe56b9e6SYuval Mintz 30fe56b9e6SYuval Mintz struct qed_pi_info { 31fe56b9e6SYuval Mintz qed_int_comp_cb_t comp_cb; 32fe56b9e6SYuval Mintz void *cookie; 33fe56b9e6SYuval Mintz }; 34fe56b9e6SYuval Mintz 35fe56b9e6SYuval Mintz struct qed_sb_sp_info { 36fe56b9e6SYuval Mintz struct qed_sb_info sb_info; 37fe56b9e6SYuval Mintz 38fe56b9e6SYuval Mintz /* per protocol index data */ 39fe56b9e6SYuval Mintz struct qed_pi_info pi_info_arr[PIS_PER_SB]; 40fe56b9e6SYuval Mintz }; 41fe56b9e6SYuval Mintz 42cc875c2eSYuval Mintz #define SB_ATTN_ALIGNED_SIZE(p_hwfn) \ 43cc875c2eSYuval Mintz ALIGNED_TYPE_SIZE(struct atten_status_block, p_hwfn) 44cc875c2eSYuval Mintz 450d956e8aSYuval Mintz struct aeu_invert_reg_bit { 460d956e8aSYuval Mintz char bit_name[30]; 470d956e8aSYuval Mintz 480d956e8aSYuval Mintz #define ATTENTION_PARITY (1 << 0) 490d956e8aSYuval Mintz 500d956e8aSYuval Mintz #define ATTENTION_LENGTH_MASK (0x00000ff0) 510d956e8aSYuval Mintz #define ATTENTION_LENGTH_SHIFT (4) 520d956e8aSYuval Mintz #define ATTENTION_LENGTH(flags) (((flags) & ATTENTION_LENGTH_MASK) >> \ 530d956e8aSYuval Mintz ATTENTION_LENGTH_SHIFT) 540d956e8aSYuval Mintz #define ATTENTION_SINGLE (1 << ATTENTION_LENGTH_SHIFT) 550d956e8aSYuval Mintz #define ATTENTION_PAR (ATTENTION_SINGLE | ATTENTION_PARITY) 560d956e8aSYuval Mintz #define ATTENTION_PAR_INT ((2 << ATTENTION_LENGTH_SHIFT) | \ 570d956e8aSYuval Mintz ATTENTION_PARITY) 580d956e8aSYuval Mintz 590d956e8aSYuval Mintz /* Multiple bits start with this offset */ 600d956e8aSYuval Mintz #define ATTENTION_OFFSET_MASK (0x000ff000) 610d956e8aSYuval Mintz #define ATTENTION_OFFSET_SHIFT (12) 620d956e8aSYuval Mintz unsigned int flags; 630d956e8aSYuval Mintz }; 640d956e8aSYuval Mintz 650d956e8aSYuval Mintz struct aeu_invert_reg { 660d956e8aSYuval Mintz struct aeu_invert_reg_bit bits[32]; 670d956e8aSYuval Mintz }; 680d956e8aSYuval Mintz 690d956e8aSYuval Mintz #define MAX_ATTN_GRPS (8) 700d956e8aSYuval Mintz #define NUM_ATTN_REGS (9) 710d956e8aSYuval Mintz 720d956e8aSYuval Mintz /* Notice aeu_invert_reg must be defined in the same order of bits as HW; */ 730d956e8aSYuval Mintz static struct aeu_invert_reg aeu_descs[NUM_ATTN_REGS] = { 740d956e8aSYuval Mintz { 750d956e8aSYuval Mintz { /* After Invert 1 */ 760d956e8aSYuval Mintz {"GPIO0 function%d", 770d956e8aSYuval Mintz (32 << ATTENTION_LENGTH_SHIFT)}, 780d956e8aSYuval Mintz } 790d956e8aSYuval Mintz }, 800d956e8aSYuval Mintz 810d956e8aSYuval Mintz { 820d956e8aSYuval Mintz { /* After Invert 2 */ 830d956e8aSYuval Mintz {"PGLUE config_space", ATTENTION_SINGLE}, 840d956e8aSYuval Mintz {"PGLUE misc_flr", ATTENTION_SINGLE}, 850d956e8aSYuval Mintz {"PGLUE B RBC", ATTENTION_PAR_INT}, 860d956e8aSYuval Mintz {"PGLUE misc_mctp", ATTENTION_SINGLE}, 870d956e8aSYuval Mintz {"Flash event", ATTENTION_SINGLE}, 880d956e8aSYuval Mintz {"SMB event", ATTENTION_SINGLE}, 890d956e8aSYuval Mintz {"Main Power", ATTENTION_SINGLE}, 900d956e8aSYuval Mintz {"SW timers #%d", (8 << ATTENTION_LENGTH_SHIFT) | 910d956e8aSYuval Mintz (1 << ATTENTION_OFFSET_SHIFT)}, 920d956e8aSYuval Mintz {"PCIE glue/PXP VPD %d", 930d956e8aSYuval Mintz (16 << ATTENTION_LENGTH_SHIFT)}, 940d956e8aSYuval Mintz } 950d956e8aSYuval Mintz }, 960d956e8aSYuval Mintz 970d956e8aSYuval Mintz { 980d956e8aSYuval Mintz { /* After Invert 3 */ 990d956e8aSYuval Mintz {"General Attention %d", 1000d956e8aSYuval Mintz (32 << ATTENTION_LENGTH_SHIFT)}, 1010d956e8aSYuval Mintz } 1020d956e8aSYuval Mintz }, 1030d956e8aSYuval Mintz 1040d956e8aSYuval Mintz { 1050d956e8aSYuval Mintz { /* After Invert 4 */ 1060d956e8aSYuval Mintz {"General Attention 32", ATTENTION_SINGLE}, 1070d956e8aSYuval Mintz {"General Attention %d", 1080d956e8aSYuval Mintz (2 << ATTENTION_LENGTH_SHIFT) | 1090d956e8aSYuval Mintz (33 << ATTENTION_OFFSET_SHIFT)}, 1100d956e8aSYuval Mintz {"General Attention 35", ATTENTION_SINGLE}, 1110d956e8aSYuval Mintz {"CNIG port %d", (4 << ATTENTION_LENGTH_SHIFT)}, 1120d956e8aSYuval Mintz {"MCP CPU", ATTENTION_SINGLE}, 1130d956e8aSYuval Mintz {"MCP Watchdog timer", ATTENTION_SINGLE}, 1140d956e8aSYuval Mintz {"MCP M2P", ATTENTION_SINGLE}, 1150d956e8aSYuval Mintz {"AVS stop status ready", ATTENTION_SINGLE}, 1160d956e8aSYuval Mintz {"MSTAT", ATTENTION_PAR_INT}, 1170d956e8aSYuval Mintz {"MSTAT per-path", ATTENTION_PAR_INT}, 1180d956e8aSYuval Mintz {"Reserved %d", (6 << ATTENTION_LENGTH_SHIFT)}, 1190d956e8aSYuval Mintz {"NIG", ATTENTION_PAR_INT}, 1200d956e8aSYuval Mintz {"BMB/OPTE/MCP", ATTENTION_PAR_INT}, 1210d956e8aSYuval Mintz {"BTB", ATTENTION_PAR_INT}, 1220d956e8aSYuval Mintz {"BRB", ATTENTION_PAR_INT}, 1230d956e8aSYuval Mintz {"PRS", ATTENTION_PAR_INT}, 1240d956e8aSYuval Mintz } 1250d956e8aSYuval Mintz }, 1260d956e8aSYuval Mintz 1270d956e8aSYuval Mintz { 1280d956e8aSYuval Mintz { /* After Invert 5 */ 1290d956e8aSYuval Mintz {"SRC", ATTENTION_PAR_INT}, 1300d956e8aSYuval Mintz {"PB Client1", ATTENTION_PAR_INT}, 1310d956e8aSYuval Mintz {"PB Client2", ATTENTION_PAR_INT}, 1320d956e8aSYuval Mintz {"RPB", ATTENTION_PAR_INT}, 1330d956e8aSYuval Mintz {"PBF", ATTENTION_PAR_INT}, 1340d956e8aSYuval Mintz {"QM", ATTENTION_PAR_INT}, 1350d956e8aSYuval Mintz {"TM", ATTENTION_PAR_INT}, 1360d956e8aSYuval Mintz {"MCM", ATTENTION_PAR_INT}, 1370d956e8aSYuval Mintz {"MSDM", ATTENTION_PAR_INT}, 1380d956e8aSYuval Mintz {"MSEM", ATTENTION_PAR_INT}, 1390d956e8aSYuval Mintz {"PCM", ATTENTION_PAR_INT}, 1400d956e8aSYuval Mintz {"PSDM", ATTENTION_PAR_INT}, 1410d956e8aSYuval Mintz {"PSEM", ATTENTION_PAR_INT}, 1420d956e8aSYuval Mintz {"TCM", ATTENTION_PAR_INT}, 1430d956e8aSYuval Mintz {"TSDM", ATTENTION_PAR_INT}, 1440d956e8aSYuval Mintz {"TSEM", ATTENTION_PAR_INT}, 1450d956e8aSYuval Mintz } 1460d956e8aSYuval Mintz }, 1470d956e8aSYuval Mintz 1480d956e8aSYuval Mintz { 1490d956e8aSYuval Mintz { /* After Invert 6 */ 1500d956e8aSYuval Mintz {"UCM", ATTENTION_PAR_INT}, 1510d956e8aSYuval Mintz {"USDM", ATTENTION_PAR_INT}, 1520d956e8aSYuval Mintz {"USEM", ATTENTION_PAR_INT}, 1530d956e8aSYuval Mintz {"XCM", ATTENTION_PAR_INT}, 1540d956e8aSYuval Mintz {"XSDM", ATTENTION_PAR_INT}, 1550d956e8aSYuval Mintz {"XSEM", ATTENTION_PAR_INT}, 1560d956e8aSYuval Mintz {"YCM", ATTENTION_PAR_INT}, 1570d956e8aSYuval Mintz {"YSDM", ATTENTION_PAR_INT}, 1580d956e8aSYuval Mintz {"YSEM", ATTENTION_PAR_INT}, 1590d956e8aSYuval Mintz {"XYLD", ATTENTION_PAR_INT}, 1600d956e8aSYuval Mintz {"TMLD", ATTENTION_PAR_INT}, 1610d956e8aSYuval Mintz {"MYLD", ATTENTION_PAR_INT}, 1620d956e8aSYuval Mintz {"YULD", ATTENTION_PAR_INT}, 1630d956e8aSYuval Mintz {"DORQ", ATTENTION_PAR_INT}, 1640d956e8aSYuval Mintz {"DBG", ATTENTION_PAR_INT}, 1650d956e8aSYuval Mintz {"IPC", ATTENTION_PAR_INT}, 1660d956e8aSYuval Mintz } 1670d956e8aSYuval Mintz }, 1680d956e8aSYuval Mintz 1690d956e8aSYuval Mintz { 1700d956e8aSYuval Mintz { /* After Invert 7 */ 1710d956e8aSYuval Mintz {"CCFC", ATTENTION_PAR_INT}, 1720d956e8aSYuval Mintz {"CDU", ATTENTION_PAR_INT}, 1730d956e8aSYuval Mintz {"DMAE", ATTENTION_PAR_INT}, 1740d956e8aSYuval Mintz {"IGU", ATTENTION_PAR_INT}, 1750d956e8aSYuval Mintz {"ATC", ATTENTION_PAR_INT}, 1760d956e8aSYuval Mintz {"CAU", ATTENTION_PAR_INT}, 1770d956e8aSYuval Mintz {"PTU", ATTENTION_PAR_INT}, 1780d956e8aSYuval Mintz {"PRM", ATTENTION_PAR_INT}, 1790d956e8aSYuval Mintz {"TCFC", ATTENTION_PAR_INT}, 1800d956e8aSYuval Mintz {"RDIF", ATTENTION_PAR_INT}, 1810d956e8aSYuval Mintz {"TDIF", ATTENTION_PAR_INT}, 1820d956e8aSYuval Mintz {"RSS", ATTENTION_PAR_INT}, 1830d956e8aSYuval Mintz {"MISC", ATTENTION_PAR_INT}, 1840d956e8aSYuval Mintz {"MISCS", ATTENTION_PAR_INT}, 1850d956e8aSYuval Mintz {"PCIE", ATTENTION_PAR}, 1860d956e8aSYuval Mintz {"Vaux PCI core", ATTENTION_SINGLE}, 1870d956e8aSYuval Mintz {"PSWRQ", ATTENTION_PAR_INT}, 1880d956e8aSYuval Mintz } 1890d956e8aSYuval Mintz }, 1900d956e8aSYuval Mintz 1910d956e8aSYuval Mintz { 1920d956e8aSYuval Mintz { /* After Invert 8 */ 1930d956e8aSYuval Mintz {"PSWRQ (pci_clk)", ATTENTION_PAR_INT}, 1940d956e8aSYuval Mintz {"PSWWR", ATTENTION_PAR_INT}, 1950d956e8aSYuval Mintz {"PSWWR (pci_clk)", ATTENTION_PAR_INT}, 1960d956e8aSYuval Mintz {"PSWRD", ATTENTION_PAR_INT}, 1970d956e8aSYuval Mintz {"PSWRD (pci_clk)", ATTENTION_PAR_INT}, 1980d956e8aSYuval Mintz {"PSWHST", ATTENTION_PAR_INT}, 1990d956e8aSYuval Mintz {"PSWHST (pci_clk)", ATTENTION_PAR_INT}, 2000d956e8aSYuval Mintz {"GRC", ATTENTION_PAR_INT}, 2010d956e8aSYuval Mintz {"CPMU", ATTENTION_PAR_INT}, 2020d956e8aSYuval Mintz {"NCSI", ATTENTION_PAR_INT}, 2030d956e8aSYuval Mintz {"MSEM PRAM", ATTENTION_PAR}, 2040d956e8aSYuval Mintz {"PSEM PRAM", ATTENTION_PAR}, 2050d956e8aSYuval Mintz {"TSEM PRAM", ATTENTION_PAR}, 2060d956e8aSYuval Mintz {"USEM PRAM", ATTENTION_PAR}, 2070d956e8aSYuval Mintz {"XSEM PRAM", ATTENTION_PAR}, 2080d956e8aSYuval Mintz {"YSEM PRAM", ATTENTION_PAR}, 2090d956e8aSYuval Mintz {"pxp_misc_mps", ATTENTION_PAR}, 2100d956e8aSYuval Mintz {"PCIE glue/PXP Exp. ROM", ATTENTION_SINGLE}, 2110d956e8aSYuval Mintz {"PERST_B assertion", ATTENTION_SINGLE}, 2120d956e8aSYuval Mintz {"PERST_B deassertion", ATTENTION_SINGLE}, 2130d956e8aSYuval Mintz {"Reserved %d", (2 << ATTENTION_LENGTH_SHIFT)}, 2140d956e8aSYuval Mintz } 2150d956e8aSYuval Mintz }, 2160d956e8aSYuval Mintz 2170d956e8aSYuval Mintz { 2180d956e8aSYuval Mintz { /* After Invert 9 */ 2190d956e8aSYuval Mintz {"MCP Latched memory", ATTENTION_PAR}, 2200d956e8aSYuval Mintz {"MCP Latched scratchpad cache", ATTENTION_SINGLE}, 2210d956e8aSYuval Mintz {"MCP Latched ump_tx", ATTENTION_PAR}, 2220d956e8aSYuval Mintz {"MCP Latched scratchpad", ATTENTION_PAR}, 2230d956e8aSYuval Mintz {"Reserved %d", (28 << ATTENTION_LENGTH_SHIFT)}, 2240d956e8aSYuval Mintz } 2250d956e8aSYuval Mintz }, 2260d956e8aSYuval Mintz }; 2270d956e8aSYuval Mintz 228cc875c2eSYuval Mintz #define ATTN_STATE_BITS (0xfff) 229cc875c2eSYuval Mintz #define ATTN_BITS_MASKABLE (0x3ff) 230cc875c2eSYuval Mintz struct qed_sb_attn_info { 231cc875c2eSYuval Mintz /* Virtual & Physical address of the SB */ 232cc875c2eSYuval Mintz struct atten_status_block *sb_attn; 233cc875c2eSYuval Mintz dma_addr_t sb_phys; 234cc875c2eSYuval Mintz 235cc875c2eSYuval Mintz /* Last seen running index */ 236cc875c2eSYuval Mintz u16 index; 237cc875c2eSYuval Mintz 2380d956e8aSYuval Mintz /* A mask of the AEU bits resulting in a parity error */ 2390d956e8aSYuval Mintz u32 parity_mask[NUM_ATTN_REGS]; 2400d956e8aSYuval Mintz 2410d956e8aSYuval Mintz /* A pointer to the attention description structure */ 2420d956e8aSYuval Mintz struct aeu_invert_reg *p_aeu_desc; 2430d956e8aSYuval Mintz 244cc875c2eSYuval Mintz /* Previously asserted attentions, which are still unasserted */ 245cc875c2eSYuval Mintz u16 known_attn; 246cc875c2eSYuval Mintz 247cc875c2eSYuval Mintz /* Cleanup address for the link's general hw attention */ 248cc875c2eSYuval Mintz u32 mfw_attn_addr; 249cc875c2eSYuval Mintz }; 250cc875c2eSYuval Mintz 251cc875c2eSYuval Mintz static inline u16 qed_attn_update_idx(struct qed_hwfn *p_hwfn, 252cc875c2eSYuval Mintz struct qed_sb_attn_info *p_sb_desc) 253cc875c2eSYuval Mintz { 254cc875c2eSYuval Mintz u16 rc = 0; 255cc875c2eSYuval Mintz u16 index; 256cc875c2eSYuval Mintz 257cc875c2eSYuval Mintz /* Make certain HW write took affect */ 258cc875c2eSYuval Mintz mmiowb(); 259cc875c2eSYuval Mintz 260cc875c2eSYuval Mintz index = le16_to_cpu(p_sb_desc->sb_attn->sb_index); 261cc875c2eSYuval Mintz if (p_sb_desc->index != index) { 262cc875c2eSYuval Mintz p_sb_desc->index = index; 263cc875c2eSYuval Mintz rc = QED_SB_ATT_IDX; 264cc875c2eSYuval Mintz } 265cc875c2eSYuval Mintz 266cc875c2eSYuval Mintz /* Make certain we got a consistent view with HW */ 267cc875c2eSYuval Mintz mmiowb(); 268cc875c2eSYuval Mintz 269cc875c2eSYuval Mintz return rc; 270cc875c2eSYuval Mintz } 271cc875c2eSYuval Mintz 272cc875c2eSYuval Mintz /** 273cc875c2eSYuval Mintz * @brief qed_int_assertion - handles asserted attention bits 274cc875c2eSYuval Mintz * 275cc875c2eSYuval Mintz * @param p_hwfn 276cc875c2eSYuval Mintz * @param asserted_bits newly asserted bits 277cc875c2eSYuval Mintz * @return int 278cc875c2eSYuval Mintz */ 279cc875c2eSYuval Mintz static int qed_int_assertion(struct qed_hwfn *p_hwfn, 280cc875c2eSYuval Mintz u16 asserted_bits) 281cc875c2eSYuval Mintz { 282cc875c2eSYuval Mintz struct qed_sb_attn_info *sb_attn_sw = p_hwfn->p_sb_attn; 283cc875c2eSYuval Mintz u32 igu_mask; 284cc875c2eSYuval Mintz 285cc875c2eSYuval Mintz /* Mask the source of the attention in the IGU */ 286cc875c2eSYuval Mintz igu_mask = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, 287cc875c2eSYuval Mintz IGU_REG_ATTENTION_ENABLE); 288cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "IGU mask: 0x%08x --> 0x%08x\n", 289cc875c2eSYuval Mintz igu_mask, igu_mask & ~(asserted_bits & ATTN_BITS_MASKABLE)); 290cc875c2eSYuval Mintz igu_mask &= ~(asserted_bits & ATTN_BITS_MASKABLE); 291cc875c2eSYuval Mintz qed_wr(p_hwfn, p_hwfn->p_dpc_ptt, IGU_REG_ATTENTION_ENABLE, igu_mask); 292cc875c2eSYuval Mintz 293cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 294cc875c2eSYuval Mintz "inner known ATTN state: 0x%04x --> 0x%04x\n", 295cc875c2eSYuval Mintz sb_attn_sw->known_attn, 296cc875c2eSYuval Mintz sb_attn_sw->known_attn | asserted_bits); 297cc875c2eSYuval Mintz sb_attn_sw->known_attn |= asserted_bits; 298cc875c2eSYuval Mintz 299cc875c2eSYuval Mintz /* Handle MCP events */ 300cc875c2eSYuval Mintz if (asserted_bits & 0x100) { 301cc875c2eSYuval Mintz qed_mcp_handle_events(p_hwfn, p_hwfn->p_dpc_ptt); 302cc875c2eSYuval Mintz /* Clean the MCP attention */ 303cc875c2eSYuval Mintz qed_wr(p_hwfn, p_hwfn->p_dpc_ptt, 304cc875c2eSYuval Mintz sb_attn_sw->mfw_attn_addr, 0); 305cc875c2eSYuval Mintz } 306cc875c2eSYuval Mintz 307cc875c2eSYuval Mintz DIRECT_REG_WR((u8 __iomem *)p_hwfn->regview + 308cc875c2eSYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 309cc875c2eSYuval Mintz ((IGU_CMD_ATTN_BIT_SET_UPPER - 310cc875c2eSYuval Mintz IGU_CMD_INT_ACK_BASE) << 3), 311cc875c2eSYuval Mintz (u32)asserted_bits); 312cc875c2eSYuval Mintz 313cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "set cmd IGU: 0x%04x\n", 314cc875c2eSYuval Mintz asserted_bits); 315cc875c2eSYuval Mintz 316cc875c2eSYuval Mintz return 0; 317cc875c2eSYuval Mintz } 318cc875c2eSYuval Mintz 319cc875c2eSYuval Mintz /** 3200d956e8aSYuval Mintz * @brief qed_int_deassertion_aeu_bit - handles the effects of a single 3210d956e8aSYuval Mintz * cause of the attention 3220d956e8aSYuval Mintz * 3230d956e8aSYuval Mintz * @param p_hwfn 3240d956e8aSYuval Mintz * @param p_aeu - descriptor of an AEU bit which caused the attention 3250d956e8aSYuval Mintz * @param aeu_en_reg - register offset of the AEU enable reg. which configured 3260d956e8aSYuval Mintz * this bit to this group. 3270d956e8aSYuval Mintz * @param bit_index - index of this bit in the aeu_en_reg 3280d956e8aSYuval Mintz * 3290d956e8aSYuval Mintz * @return int 3300d956e8aSYuval Mintz */ 3310d956e8aSYuval Mintz static int 3320d956e8aSYuval Mintz qed_int_deassertion_aeu_bit(struct qed_hwfn *p_hwfn, 3330d956e8aSYuval Mintz struct aeu_invert_reg_bit *p_aeu, 3340d956e8aSYuval Mintz u32 aeu_en_reg, 3350d956e8aSYuval Mintz u32 bitmask) 3360d956e8aSYuval Mintz { 3370d956e8aSYuval Mintz int rc = -EINVAL; 3380d956e8aSYuval Mintz u32 val, mask = ~bitmask; 3390d956e8aSYuval Mintz 3400d956e8aSYuval Mintz DP_INFO(p_hwfn, "Deasserted attention `%s'[%08x]\n", 3410d956e8aSYuval Mintz p_aeu->bit_name, bitmask); 3420d956e8aSYuval Mintz 3430d956e8aSYuval Mintz /* Prevent this Attention from being asserted in the future */ 3440d956e8aSYuval Mintz val = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, aeu_en_reg); 3450d956e8aSYuval Mintz qed_wr(p_hwfn, p_hwfn->p_dpc_ptt, aeu_en_reg, (val & mask)); 3460d956e8aSYuval Mintz DP_INFO(p_hwfn, "`%s' - Disabled future attentions\n", 3470d956e8aSYuval Mintz p_aeu->bit_name); 3480d956e8aSYuval Mintz 3490d956e8aSYuval Mintz return rc; 3500d956e8aSYuval Mintz } 3510d956e8aSYuval Mintz 3520d956e8aSYuval Mintz /** 353cc875c2eSYuval Mintz * @brief - handles deassertion of previously asserted attentions. 354cc875c2eSYuval Mintz * 355cc875c2eSYuval Mintz * @param p_hwfn 356cc875c2eSYuval Mintz * @param deasserted_bits - newly deasserted bits 357cc875c2eSYuval Mintz * @return int 358cc875c2eSYuval Mintz * 359cc875c2eSYuval Mintz */ 360cc875c2eSYuval Mintz static int qed_int_deassertion(struct qed_hwfn *p_hwfn, 361cc875c2eSYuval Mintz u16 deasserted_bits) 362cc875c2eSYuval Mintz { 363cc875c2eSYuval Mintz struct qed_sb_attn_info *sb_attn_sw = p_hwfn->p_sb_attn; 3640d956e8aSYuval Mintz u32 aeu_inv_arr[NUM_ATTN_REGS], aeu_mask; 3650d956e8aSYuval Mintz u8 i, j, k, bit_idx; 3660d956e8aSYuval Mintz int rc = 0; 367cc875c2eSYuval Mintz 3680d956e8aSYuval Mintz /* Read the attention registers in the AEU */ 3690d956e8aSYuval Mintz for (i = 0; i < NUM_ATTN_REGS; i++) { 3700d956e8aSYuval Mintz aeu_inv_arr[i] = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, 3710d956e8aSYuval Mintz MISC_REG_AEU_AFTER_INVERT_1_IGU + 3720d956e8aSYuval Mintz i * 0x4); 3730d956e8aSYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 3740d956e8aSYuval Mintz "Deasserted bits [%d]: %08x\n", 3750d956e8aSYuval Mintz i, aeu_inv_arr[i]); 3760d956e8aSYuval Mintz } 3770d956e8aSYuval Mintz 3780d956e8aSYuval Mintz /* Find parity attentions first */ 3790d956e8aSYuval Mintz for (i = 0; i < NUM_ATTN_REGS; i++) { 3800d956e8aSYuval Mintz struct aeu_invert_reg *p_aeu = &sb_attn_sw->p_aeu_desc[i]; 3810d956e8aSYuval Mintz u32 en = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, 3820d956e8aSYuval Mintz MISC_REG_AEU_ENABLE1_IGU_OUT_0 + 3830d956e8aSYuval Mintz i * sizeof(u32)); 3840d956e8aSYuval Mintz u32 parities; 3850d956e8aSYuval Mintz 3860d956e8aSYuval Mintz /* Skip register in which no parity bit is currently set */ 3870d956e8aSYuval Mintz parities = sb_attn_sw->parity_mask[i] & aeu_inv_arr[i] & en; 3880d956e8aSYuval Mintz if (!parities) 3890d956e8aSYuval Mintz continue; 3900d956e8aSYuval Mintz 3910d956e8aSYuval Mintz for (j = 0, bit_idx = 0; bit_idx < 32; j++) { 3920d956e8aSYuval Mintz struct aeu_invert_reg_bit *p_bit = &p_aeu->bits[j]; 3930d956e8aSYuval Mintz 3940d956e8aSYuval Mintz if ((p_bit->flags & ATTENTION_PARITY) && 3950d956e8aSYuval Mintz !!(parities & (1 << bit_idx))) { 3960d956e8aSYuval Mintz DP_INFO(p_hwfn, 3970d956e8aSYuval Mintz "%s[%d] parity attention is set\n", 3980d956e8aSYuval Mintz p_bit->bit_name, bit_idx); 3990d956e8aSYuval Mintz } 4000d956e8aSYuval Mintz 4010d956e8aSYuval Mintz bit_idx += ATTENTION_LENGTH(p_bit->flags); 4020d956e8aSYuval Mintz } 4030d956e8aSYuval Mintz } 4040d956e8aSYuval Mintz 4050d956e8aSYuval Mintz /* Find non-parity cause for attention and act */ 4060d956e8aSYuval Mintz for (k = 0; k < MAX_ATTN_GRPS; k++) { 4070d956e8aSYuval Mintz struct aeu_invert_reg_bit *p_aeu; 4080d956e8aSYuval Mintz 4090d956e8aSYuval Mintz /* Handle only groups whose attention is currently deasserted */ 4100d956e8aSYuval Mintz if (!(deasserted_bits & (1 << k))) 4110d956e8aSYuval Mintz continue; 4120d956e8aSYuval Mintz 4130d956e8aSYuval Mintz for (i = 0; i < NUM_ATTN_REGS; i++) { 4140d956e8aSYuval Mintz u32 aeu_en = MISC_REG_AEU_ENABLE1_IGU_OUT_0 + 4150d956e8aSYuval Mintz i * sizeof(u32) + 4160d956e8aSYuval Mintz k * sizeof(u32) * NUM_ATTN_REGS; 4170d956e8aSYuval Mintz u32 en, bits; 4180d956e8aSYuval Mintz 4190d956e8aSYuval Mintz en = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, aeu_en); 4200d956e8aSYuval Mintz bits = aeu_inv_arr[i] & en; 4210d956e8aSYuval Mintz 4220d956e8aSYuval Mintz /* Skip if no bit from this group is currently set */ 4230d956e8aSYuval Mintz if (!bits) 4240d956e8aSYuval Mintz continue; 4250d956e8aSYuval Mintz 4260d956e8aSYuval Mintz /* Find all set bits from current register which belong 4270d956e8aSYuval Mintz * to current group, making them responsible for the 4280d956e8aSYuval Mintz * previous assertion. 4290d956e8aSYuval Mintz */ 4300d956e8aSYuval Mintz for (j = 0, bit_idx = 0; bit_idx < 32; j++) { 4310d956e8aSYuval Mintz u8 bit, bit_len; 4320d956e8aSYuval Mintz u32 bitmask; 4330d956e8aSYuval Mintz 4340d956e8aSYuval Mintz p_aeu = &sb_attn_sw->p_aeu_desc[i].bits[j]; 4350d956e8aSYuval Mintz 4360d956e8aSYuval Mintz /* No need to handle parity-only bits */ 4370d956e8aSYuval Mintz if (p_aeu->flags == ATTENTION_PAR) 4380d956e8aSYuval Mintz continue; 4390d956e8aSYuval Mintz 4400d956e8aSYuval Mintz bit = bit_idx; 4410d956e8aSYuval Mintz bit_len = ATTENTION_LENGTH(p_aeu->flags); 4420d956e8aSYuval Mintz if (p_aeu->flags & ATTENTION_PAR_INT) { 4430d956e8aSYuval Mintz /* Skip Parity */ 4440d956e8aSYuval Mintz bit++; 4450d956e8aSYuval Mintz bit_len--; 4460d956e8aSYuval Mintz } 4470d956e8aSYuval Mintz 4480d956e8aSYuval Mintz bitmask = bits & (((1 << bit_len) - 1) << bit); 4490d956e8aSYuval Mintz if (bitmask) { 4500d956e8aSYuval Mintz /* Handle source of the attention */ 4510d956e8aSYuval Mintz qed_int_deassertion_aeu_bit(p_hwfn, 4520d956e8aSYuval Mintz p_aeu, 4530d956e8aSYuval Mintz aeu_en, 4540d956e8aSYuval Mintz bitmask); 4550d956e8aSYuval Mintz } 4560d956e8aSYuval Mintz 4570d956e8aSYuval Mintz bit_idx += ATTENTION_LENGTH(p_aeu->flags); 4580d956e8aSYuval Mintz } 4590d956e8aSYuval Mintz } 4600d956e8aSYuval Mintz } 461cc875c2eSYuval Mintz 462cc875c2eSYuval Mintz /* Clear IGU indication for the deasserted bits */ 463cc875c2eSYuval Mintz DIRECT_REG_WR((u8 __iomem *)p_hwfn->regview + 464cc875c2eSYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 465cc875c2eSYuval Mintz ((IGU_CMD_ATTN_BIT_CLR_UPPER - 466cc875c2eSYuval Mintz IGU_CMD_INT_ACK_BASE) << 3), 467cc875c2eSYuval Mintz ~((u32)deasserted_bits)); 468cc875c2eSYuval Mintz 469cc875c2eSYuval Mintz /* Unmask deasserted attentions in IGU */ 470cc875c2eSYuval Mintz aeu_mask = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, 471cc875c2eSYuval Mintz IGU_REG_ATTENTION_ENABLE); 472cc875c2eSYuval Mintz aeu_mask |= (deasserted_bits & ATTN_BITS_MASKABLE); 473cc875c2eSYuval Mintz qed_wr(p_hwfn, p_hwfn->p_dpc_ptt, IGU_REG_ATTENTION_ENABLE, aeu_mask); 474cc875c2eSYuval Mintz 475cc875c2eSYuval Mintz /* Clear deassertion from inner state */ 476cc875c2eSYuval Mintz sb_attn_sw->known_attn &= ~deasserted_bits; 477cc875c2eSYuval Mintz 4780d956e8aSYuval Mintz return rc; 479cc875c2eSYuval Mintz } 480cc875c2eSYuval Mintz 481cc875c2eSYuval Mintz static int qed_int_attentions(struct qed_hwfn *p_hwfn) 482cc875c2eSYuval Mintz { 483cc875c2eSYuval Mintz struct qed_sb_attn_info *p_sb_attn_sw = p_hwfn->p_sb_attn; 484cc875c2eSYuval Mintz struct atten_status_block *p_sb_attn = p_sb_attn_sw->sb_attn; 485cc875c2eSYuval Mintz u32 attn_bits = 0, attn_acks = 0; 486cc875c2eSYuval Mintz u16 asserted_bits, deasserted_bits; 487cc875c2eSYuval Mintz __le16 index; 488cc875c2eSYuval Mintz int rc = 0; 489cc875c2eSYuval Mintz 490cc875c2eSYuval Mintz /* Read current attention bits/acks - safeguard against attentions 491cc875c2eSYuval Mintz * by guaranting work on a synchronized timeframe 492cc875c2eSYuval Mintz */ 493cc875c2eSYuval Mintz do { 494cc875c2eSYuval Mintz index = p_sb_attn->sb_index; 495cc875c2eSYuval Mintz attn_bits = le32_to_cpu(p_sb_attn->atten_bits); 496cc875c2eSYuval Mintz attn_acks = le32_to_cpu(p_sb_attn->atten_ack); 497cc875c2eSYuval Mintz } while (index != p_sb_attn->sb_index); 498cc875c2eSYuval Mintz p_sb_attn->sb_index = index; 499cc875c2eSYuval Mintz 500cc875c2eSYuval Mintz /* Attention / Deassertion are meaningful (and in correct state) 501cc875c2eSYuval Mintz * only when they differ and consistent with known state - deassertion 502cc875c2eSYuval Mintz * when previous attention & current ack, and assertion when current 503cc875c2eSYuval Mintz * attention with no previous attention 504cc875c2eSYuval Mintz */ 505cc875c2eSYuval Mintz asserted_bits = (attn_bits & ~attn_acks & ATTN_STATE_BITS) & 506cc875c2eSYuval Mintz ~p_sb_attn_sw->known_attn; 507cc875c2eSYuval Mintz deasserted_bits = (~attn_bits & attn_acks & ATTN_STATE_BITS) & 508cc875c2eSYuval Mintz p_sb_attn_sw->known_attn; 509cc875c2eSYuval Mintz 510cc875c2eSYuval Mintz if ((asserted_bits & ~0x100) || (deasserted_bits & ~0x100)) { 511cc875c2eSYuval Mintz DP_INFO(p_hwfn, 512cc875c2eSYuval Mintz "Attention: Index: 0x%04x, Bits: 0x%08x, Acks: 0x%08x, asserted: 0x%04x, De-asserted 0x%04x [Prev. known: 0x%04x]\n", 513cc875c2eSYuval Mintz index, attn_bits, attn_acks, asserted_bits, 514cc875c2eSYuval Mintz deasserted_bits, p_sb_attn_sw->known_attn); 515cc875c2eSYuval Mintz } else if (asserted_bits == 0x100) { 516cc875c2eSYuval Mintz DP_INFO(p_hwfn, 517cc875c2eSYuval Mintz "MFW indication via attention\n"); 518cc875c2eSYuval Mintz } else { 519cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 520cc875c2eSYuval Mintz "MFW indication [deassertion]\n"); 521cc875c2eSYuval Mintz } 522cc875c2eSYuval Mintz 523cc875c2eSYuval Mintz if (asserted_bits) { 524cc875c2eSYuval Mintz rc = qed_int_assertion(p_hwfn, asserted_bits); 525cc875c2eSYuval Mintz if (rc) 526cc875c2eSYuval Mintz return rc; 527cc875c2eSYuval Mintz } 528cc875c2eSYuval Mintz 529cc875c2eSYuval Mintz if (deasserted_bits) { 530cc875c2eSYuval Mintz rc = qed_int_deassertion(p_hwfn, deasserted_bits); 531cc875c2eSYuval Mintz if (rc) 532cc875c2eSYuval Mintz return rc; 533cc875c2eSYuval Mintz } 534cc875c2eSYuval Mintz 535cc875c2eSYuval Mintz return rc; 536cc875c2eSYuval Mintz } 537cc875c2eSYuval Mintz 538cc875c2eSYuval Mintz static void qed_sb_ack_attn(struct qed_hwfn *p_hwfn, 539cc875c2eSYuval Mintz void __iomem *igu_addr, 540cc875c2eSYuval Mintz u32 ack_cons) 541cc875c2eSYuval Mintz { 542cc875c2eSYuval Mintz struct igu_prod_cons_update igu_ack = { 0 }; 543cc875c2eSYuval Mintz 544cc875c2eSYuval Mintz igu_ack.sb_id_and_flags = 545cc875c2eSYuval Mintz ((ack_cons << IGU_PROD_CONS_UPDATE_SB_INDEX_SHIFT) | 546cc875c2eSYuval Mintz (1 << IGU_PROD_CONS_UPDATE_UPDATE_FLAG_SHIFT) | 547cc875c2eSYuval Mintz (IGU_INT_NOP << IGU_PROD_CONS_UPDATE_ENABLE_INT_SHIFT) | 548cc875c2eSYuval Mintz (IGU_SEG_ACCESS_ATTN << 549cc875c2eSYuval Mintz IGU_PROD_CONS_UPDATE_SEGMENT_ACCESS_SHIFT)); 550cc875c2eSYuval Mintz 551cc875c2eSYuval Mintz DIRECT_REG_WR(igu_addr, igu_ack.sb_id_and_flags); 552cc875c2eSYuval Mintz 553cc875c2eSYuval Mintz /* Both segments (interrupts & acks) are written to same place address; 554cc875c2eSYuval Mintz * Need to guarantee all commands will be received (in-order) by HW. 555cc875c2eSYuval Mintz */ 556cc875c2eSYuval Mintz mmiowb(); 557cc875c2eSYuval Mintz barrier(); 558cc875c2eSYuval Mintz } 559cc875c2eSYuval Mintz 560fe56b9e6SYuval Mintz void qed_int_sp_dpc(unsigned long hwfn_cookie) 561fe56b9e6SYuval Mintz { 562fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = (struct qed_hwfn *)hwfn_cookie; 563fe56b9e6SYuval Mintz struct qed_pi_info *pi_info = NULL; 564cc875c2eSYuval Mintz struct qed_sb_attn_info *sb_attn; 565fe56b9e6SYuval Mintz struct qed_sb_info *sb_info; 566fe56b9e6SYuval Mintz int arr_size; 567fe56b9e6SYuval Mintz u16 rc = 0; 568fe56b9e6SYuval Mintz 569fe56b9e6SYuval Mintz if (!p_hwfn->p_sp_sb) { 570fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, "DPC called - no p_sp_sb\n"); 571fe56b9e6SYuval Mintz return; 572fe56b9e6SYuval Mintz } 573fe56b9e6SYuval Mintz 574fe56b9e6SYuval Mintz sb_info = &p_hwfn->p_sp_sb->sb_info; 575fe56b9e6SYuval Mintz arr_size = ARRAY_SIZE(p_hwfn->p_sp_sb->pi_info_arr); 576fe56b9e6SYuval Mintz if (!sb_info) { 577fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, 578fe56b9e6SYuval Mintz "Status block is NULL - cannot ack interrupts\n"); 579fe56b9e6SYuval Mintz return; 580fe56b9e6SYuval Mintz } 581fe56b9e6SYuval Mintz 582cc875c2eSYuval Mintz if (!p_hwfn->p_sb_attn) { 583cc875c2eSYuval Mintz DP_ERR(p_hwfn->cdev, "DPC called - no p_sb_attn"); 584cc875c2eSYuval Mintz return; 585cc875c2eSYuval Mintz } 586cc875c2eSYuval Mintz sb_attn = p_hwfn->p_sb_attn; 587cc875c2eSYuval Mintz 588fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "DPC Called! (hwfn %p %d)\n", 589fe56b9e6SYuval Mintz p_hwfn, p_hwfn->my_id); 590fe56b9e6SYuval Mintz 591fe56b9e6SYuval Mintz /* Disable ack for def status block. Required both for msix + 592fe56b9e6SYuval Mintz * inta in non-mask mode, in inta does no harm. 593fe56b9e6SYuval Mintz */ 594fe56b9e6SYuval Mintz qed_sb_ack(sb_info, IGU_INT_DISABLE, 0); 595fe56b9e6SYuval Mintz 596fe56b9e6SYuval Mintz /* Gather Interrupts/Attentions information */ 597fe56b9e6SYuval Mintz if (!sb_info->sb_virt) { 598fe56b9e6SYuval Mintz DP_ERR( 599fe56b9e6SYuval Mintz p_hwfn->cdev, 600fe56b9e6SYuval Mintz "Interrupt Status block is NULL - cannot check for new interrupts!\n"); 601fe56b9e6SYuval Mintz } else { 602fe56b9e6SYuval Mintz u32 tmp_index = sb_info->sb_ack; 603fe56b9e6SYuval Mintz 604fe56b9e6SYuval Mintz rc = qed_sb_update_sb_idx(sb_info); 605fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn->cdev, NETIF_MSG_INTR, 606fe56b9e6SYuval Mintz "Interrupt indices: 0x%08x --> 0x%08x\n", 607fe56b9e6SYuval Mintz tmp_index, sb_info->sb_ack); 608fe56b9e6SYuval Mintz } 609fe56b9e6SYuval Mintz 610cc875c2eSYuval Mintz if (!sb_attn || !sb_attn->sb_attn) { 611cc875c2eSYuval Mintz DP_ERR( 612cc875c2eSYuval Mintz p_hwfn->cdev, 613cc875c2eSYuval Mintz "Attentions Status block is NULL - cannot check for new attentions!\n"); 614cc875c2eSYuval Mintz } else { 615cc875c2eSYuval Mintz u16 tmp_index = sb_attn->index; 616cc875c2eSYuval Mintz 617cc875c2eSYuval Mintz rc |= qed_attn_update_idx(p_hwfn, sb_attn); 618cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn->cdev, NETIF_MSG_INTR, 619cc875c2eSYuval Mintz "Attention indices: 0x%08x --> 0x%08x\n", 620cc875c2eSYuval Mintz tmp_index, sb_attn->index); 621cc875c2eSYuval Mintz } 622cc875c2eSYuval Mintz 623fe56b9e6SYuval Mintz /* Check if we expect interrupts at this time. if not just ack them */ 624fe56b9e6SYuval Mintz if (!(rc & QED_SB_EVENT_MASK)) { 625fe56b9e6SYuval Mintz qed_sb_ack(sb_info, IGU_INT_ENABLE, 1); 626fe56b9e6SYuval Mintz return; 627fe56b9e6SYuval Mintz } 628fe56b9e6SYuval Mintz 629fe56b9e6SYuval Mintz /* Check the validity of the DPC ptt. If not ack interrupts and fail */ 630fe56b9e6SYuval Mintz if (!p_hwfn->p_dpc_ptt) { 631fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn->cdev, "Failed to allocate PTT\n"); 632fe56b9e6SYuval Mintz qed_sb_ack(sb_info, IGU_INT_ENABLE, 1); 633fe56b9e6SYuval Mintz return; 634fe56b9e6SYuval Mintz } 635fe56b9e6SYuval Mintz 636cc875c2eSYuval Mintz if (rc & QED_SB_ATT_IDX) 637cc875c2eSYuval Mintz qed_int_attentions(p_hwfn); 638cc875c2eSYuval Mintz 639fe56b9e6SYuval Mintz if (rc & QED_SB_IDX) { 640fe56b9e6SYuval Mintz int pi; 641fe56b9e6SYuval Mintz 642fe56b9e6SYuval Mintz /* Look for a free index */ 643fe56b9e6SYuval Mintz for (pi = 0; pi < arr_size; pi++) { 644fe56b9e6SYuval Mintz pi_info = &p_hwfn->p_sp_sb->pi_info_arr[pi]; 645fe56b9e6SYuval Mintz if (pi_info->comp_cb) 646fe56b9e6SYuval Mintz pi_info->comp_cb(p_hwfn, pi_info->cookie); 647fe56b9e6SYuval Mintz } 648fe56b9e6SYuval Mintz } 649fe56b9e6SYuval Mintz 650cc875c2eSYuval Mintz if (sb_attn && (rc & QED_SB_ATT_IDX)) 651cc875c2eSYuval Mintz /* This should be done before the interrupts are enabled, 652cc875c2eSYuval Mintz * since otherwise a new attention will be generated. 653cc875c2eSYuval Mintz */ 654cc875c2eSYuval Mintz qed_sb_ack_attn(p_hwfn, sb_info->igu_addr, sb_attn->index); 655cc875c2eSYuval Mintz 656fe56b9e6SYuval Mintz qed_sb_ack(sb_info, IGU_INT_ENABLE, 1); 657fe56b9e6SYuval Mintz } 658fe56b9e6SYuval Mintz 659cc875c2eSYuval Mintz static void qed_int_sb_attn_free(struct qed_hwfn *p_hwfn) 660cc875c2eSYuval Mintz { 661cc875c2eSYuval Mintz struct qed_sb_attn_info *p_sb = p_hwfn->p_sb_attn; 662cc875c2eSYuval Mintz 6634ac801b7SYuval Mintz if (!p_sb) 6644ac801b7SYuval Mintz return; 6654ac801b7SYuval Mintz 666cc875c2eSYuval Mintz if (p_sb->sb_attn) 6674ac801b7SYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 668cc875c2eSYuval Mintz SB_ATTN_ALIGNED_SIZE(p_hwfn), 669cc875c2eSYuval Mintz p_sb->sb_attn, 670cc875c2eSYuval Mintz p_sb->sb_phys); 671cc875c2eSYuval Mintz kfree(p_sb); 672cc875c2eSYuval Mintz } 673cc875c2eSYuval Mintz 674cc875c2eSYuval Mintz static void qed_int_sb_attn_setup(struct qed_hwfn *p_hwfn, 675cc875c2eSYuval Mintz struct qed_ptt *p_ptt) 676cc875c2eSYuval Mintz { 677cc875c2eSYuval Mintz struct qed_sb_attn_info *sb_info = p_hwfn->p_sb_attn; 678cc875c2eSYuval Mintz 679cc875c2eSYuval Mintz memset(sb_info->sb_attn, 0, sizeof(*sb_info->sb_attn)); 680cc875c2eSYuval Mintz 681cc875c2eSYuval Mintz sb_info->index = 0; 682cc875c2eSYuval Mintz sb_info->known_attn = 0; 683cc875c2eSYuval Mintz 684cc875c2eSYuval Mintz /* Configure Attention Status Block in IGU */ 685cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_ATTN_MSG_ADDR_L, 686cc875c2eSYuval Mintz lower_32_bits(p_hwfn->p_sb_attn->sb_phys)); 687cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_ATTN_MSG_ADDR_H, 688cc875c2eSYuval Mintz upper_32_bits(p_hwfn->p_sb_attn->sb_phys)); 689cc875c2eSYuval Mintz } 690cc875c2eSYuval Mintz 691cc875c2eSYuval Mintz static void qed_int_sb_attn_init(struct qed_hwfn *p_hwfn, 692cc875c2eSYuval Mintz struct qed_ptt *p_ptt, 693cc875c2eSYuval Mintz void *sb_virt_addr, 694cc875c2eSYuval Mintz dma_addr_t sb_phy_addr) 695cc875c2eSYuval Mintz { 696cc875c2eSYuval Mintz struct qed_sb_attn_info *sb_info = p_hwfn->p_sb_attn; 6970d956e8aSYuval Mintz int i, j, k; 698cc875c2eSYuval Mintz 699cc875c2eSYuval Mintz sb_info->sb_attn = sb_virt_addr; 700cc875c2eSYuval Mintz sb_info->sb_phys = sb_phy_addr; 701cc875c2eSYuval Mintz 7020d956e8aSYuval Mintz /* Set the pointer to the AEU descriptors */ 7030d956e8aSYuval Mintz sb_info->p_aeu_desc = aeu_descs; 7040d956e8aSYuval Mintz 7050d956e8aSYuval Mintz /* Calculate Parity Masks */ 7060d956e8aSYuval Mintz memset(sb_info->parity_mask, 0, sizeof(u32) * NUM_ATTN_REGS); 7070d956e8aSYuval Mintz for (i = 0; i < NUM_ATTN_REGS; i++) { 7080d956e8aSYuval Mintz /* j is array index, k is bit index */ 7090d956e8aSYuval Mintz for (j = 0, k = 0; k < 32; j++) { 7100d956e8aSYuval Mintz unsigned int flags = aeu_descs[i].bits[j].flags; 7110d956e8aSYuval Mintz 7120d956e8aSYuval Mintz if (flags & ATTENTION_PARITY) 7130d956e8aSYuval Mintz sb_info->parity_mask[i] |= 1 << k; 7140d956e8aSYuval Mintz 7150d956e8aSYuval Mintz k += ATTENTION_LENGTH(flags); 7160d956e8aSYuval Mintz } 7170d956e8aSYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 7180d956e8aSYuval Mintz "Attn Mask [Reg %d]: 0x%08x\n", 7190d956e8aSYuval Mintz i, sb_info->parity_mask[i]); 7200d956e8aSYuval Mintz } 7210d956e8aSYuval Mintz 722cc875c2eSYuval Mintz /* Set the address of cleanup for the mcp attention */ 723cc875c2eSYuval Mintz sb_info->mfw_attn_addr = (p_hwfn->rel_pf_id << 3) + 724cc875c2eSYuval Mintz MISC_REG_AEU_GENERAL_ATTN_0; 725cc875c2eSYuval Mintz 726cc875c2eSYuval Mintz qed_int_sb_attn_setup(p_hwfn, p_ptt); 727cc875c2eSYuval Mintz } 728cc875c2eSYuval Mintz 729cc875c2eSYuval Mintz static int qed_int_sb_attn_alloc(struct qed_hwfn *p_hwfn, 730cc875c2eSYuval Mintz struct qed_ptt *p_ptt) 731cc875c2eSYuval Mintz { 732cc875c2eSYuval Mintz struct qed_dev *cdev = p_hwfn->cdev; 733cc875c2eSYuval Mintz struct qed_sb_attn_info *p_sb; 734cc875c2eSYuval Mintz void *p_virt; 735cc875c2eSYuval Mintz dma_addr_t p_phys = 0; 736cc875c2eSYuval Mintz 737cc875c2eSYuval Mintz /* SB struct */ 73860fffb3bSYuval Mintz p_sb = kmalloc(sizeof(*p_sb), GFP_KERNEL); 739cc875c2eSYuval Mintz if (!p_sb) { 740cc875c2eSYuval Mintz DP_NOTICE(cdev, "Failed to allocate `struct qed_sb_attn_info'\n"); 741cc875c2eSYuval Mintz return -ENOMEM; 742cc875c2eSYuval Mintz } 743cc875c2eSYuval Mintz 744cc875c2eSYuval Mintz /* SB ring */ 745cc875c2eSYuval Mintz p_virt = dma_alloc_coherent(&cdev->pdev->dev, 746cc875c2eSYuval Mintz SB_ATTN_ALIGNED_SIZE(p_hwfn), 747cc875c2eSYuval Mintz &p_phys, GFP_KERNEL); 748cc875c2eSYuval Mintz 749cc875c2eSYuval Mintz if (!p_virt) { 750cc875c2eSYuval Mintz DP_NOTICE(cdev, "Failed to allocate status block (attentions)\n"); 751cc875c2eSYuval Mintz kfree(p_sb); 752cc875c2eSYuval Mintz return -ENOMEM; 753cc875c2eSYuval Mintz } 754cc875c2eSYuval Mintz 755cc875c2eSYuval Mintz /* Attention setup */ 756cc875c2eSYuval Mintz p_hwfn->p_sb_attn = p_sb; 757cc875c2eSYuval Mintz qed_int_sb_attn_init(p_hwfn, p_ptt, p_virt, p_phys); 758cc875c2eSYuval Mintz 759cc875c2eSYuval Mintz return 0; 760cc875c2eSYuval Mintz } 761cc875c2eSYuval Mintz 762fe56b9e6SYuval Mintz /* coalescing timeout = timeset << (timer_res + 1) */ 763fe56b9e6SYuval Mintz #define QED_CAU_DEF_RX_USECS 24 764fe56b9e6SYuval Mintz #define QED_CAU_DEF_TX_USECS 48 765fe56b9e6SYuval Mintz 766fe56b9e6SYuval Mintz void qed_init_cau_sb_entry(struct qed_hwfn *p_hwfn, 767fe56b9e6SYuval Mintz struct cau_sb_entry *p_sb_entry, 768fe56b9e6SYuval Mintz u8 pf_id, 769fe56b9e6SYuval Mintz u16 vf_number, 770fe56b9e6SYuval Mintz u8 vf_valid) 771fe56b9e6SYuval Mintz { 7724ac801b7SYuval Mintz struct qed_dev *cdev = p_hwfn->cdev; 773fe56b9e6SYuval Mintz u32 cau_state; 774fe56b9e6SYuval Mintz 775fe56b9e6SYuval Mintz memset(p_sb_entry, 0, sizeof(*p_sb_entry)); 776fe56b9e6SYuval Mintz 777fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_PF_NUMBER, pf_id); 778fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_VF_NUMBER, vf_number); 779fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_VF_VALID, vf_valid); 780fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_SB_TIMESET0, 0x7F); 781fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_SB_TIMESET1, 0x7F); 782fe56b9e6SYuval Mintz 783fe56b9e6SYuval Mintz /* setting the time resultion to a fixed value ( = 1) */ 784fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_TIMER_RES0, 785fe56b9e6SYuval Mintz QED_CAU_DEF_RX_TIMER_RES); 786fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_TIMER_RES1, 787fe56b9e6SYuval Mintz QED_CAU_DEF_TX_TIMER_RES); 788fe56b9e6SYuval Mintz 789fe56b9e6SYuval Mintz cau_state = CAU_HC_DISABLE_STATE; 790fe56b9e6SYuval Mintz 7914ac801b7SYuval Mintz if (cdev->int_coalescing_mode == QED_COAL_MODE_ENABLE) { 792fe56b9e6SYuval Mintz cau_state = CAU_HC_ENABLE_STATE; 7934ac801b7SYuval Mintz if (!cdev->rx_coalesce_usecs) 7944ac801b7SYuval Mintz cdev->rx_coalesce_usecs = QED_CAU_DEF_RX_USECS; 7954ac801b7SYuval Mintz if (!cdev->tx_coalesce_usecs) 7964ac801b7SYuval Mintz cdev->tx_coalesce_usecs = QED_CAU_DEF_TX_USECS; 797fe56b9e6SYuval Mintz } 798fe56b9e6SYuval Mintz 799fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->data, CAU_SB_ENTRY_STATE0, cau_state); 800fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->data, CAU_SB_ENTRY_STATE1, cau_state); 801fe56b9e6SYuval Mintz } 802fe56b9e6SYuval Mintz 803fe56b9e6SYuval Mintz void qed_int_cau_conf_sb(struct qed_hwfn *p_hwfn, 804fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 805fe56b9e6SYuval Mintz dma_addr_t sb_phys, 806fe56b9e6SYuval Mintz u16 igu_sb_id, 807fe56b9e6SYuval Mintz u16 vf_number, 808fe56b9e6SYuval Mintz u8 vf_valid) 809fe56b9e6SYuval Mintz { 810fe56b9e6SYuval Mintz struct cau_sb_entry sb_entry; 811fe56b9e6SYuval Mintz 812fe56b9e6SYuval Mintz qed_init_cau_sb_entry(p_hwfn, &sb_entry, p_hwfn->rel_pf_id, 813fe56b9e6SYuval Mintz vf_number, vf_valid); 814fe56b9e6SYuval Mintz 815fe56b9e6SYuval Mintz if (p_hwfn->hw_init_done) { 8160a0c5d3bSYuval Mintz /* Wide-bus, initialize via DMAE */ 8170a0c5d3bSYuval Mintz u64 phys_addr = (u64)sb_phys; 818fe56b9e6SYuval Mintz 8190a0c5d3bSYuval Mintz qed_dmae_host2grc(p_hwfn, p_ptt, (u64)(uintptr_t)&phys_addr, 8200a0c5d3bSYuval Mintz CAU_REG_SB_ADDR_MEMORY + 8210a0c5d3bSYuval Mintz igu_sb_id * sizeof(u64), 2, 0); 8220a0c5d3bSYuval Mintz qed_dmae_host2grc(p_hwfn, p_ptt, (u64)(uintptr_t)&sb_entry, 8230a0c5d3bSYuval Mintz CAU_REG_SB_VAR_MEMORY + 8240a0c5d3bSYuval Mintz igu_sb_id * sizeof(u64), 2, 0); 825fe56b9e6SYuval Mintz } else { 826fe56b9e6SYuval Mintz /* Initialize Status Block Address */ 827fe56b9e6SYuval Mintz STORE_RT_REG_AGG(p_hwfn, 828fe56b9e6SYuval Mintz CAU_REG_SB_ADDR_MEMORY_RT_OFFSET + 829fe56b9e6SYuval Mintz igu_sb_id * 2, 830fe56b9e6SYuval Mintz sb_phys); 831fe56b9e6SYuval Mintz 832fe56b9e6SYuval Mintz STORE_RT_REG_AGG(p_hwfn, 833fe56b9e6SYuval Mintz CAU_REG_SB_VAR_MEMORY_RT_OFFSET + 834fe56b9e6SYuval Mintz igu_sb_id * 2, 835fe56b9e6SYuval Mintz sb_entry); 836fe56b9e6SYuval Mintz } 837fe56b9e6SYuval Mintz 838fe56b9e6SYuval Mintz /* Configure pi coalescing if set */ 839fe56b9e6SYuval Mintz if (p_hwfn->cdev->int_coalescing_mode == QED_COAL_MODE_ENABLE) { 840fe56b9e6SYuval Mintz u8 timeset = p_hwfn->cdev->rx_coalesce_usecs >> 841fe56b9e6SYuval Mintz (QED_CAU_DEF_RX_TIMER_RES + 1); 842fe56b9e6SYuval Mintz u8 num_tc = 1, i; 843fe56b9e6SYuval Mintz 844fe56b9e6SYuval Mintz qed_int_cau_conf_pi(p_hwfn, p_ptt, igu_sb_id, RX_PI, 845fe56b9e6SYuval Mintz QED_COAL_RX_STATE_MACHINE, 846fe56b9e6SYuval Mintz timeset); 847fe56b9e6SYuval Mintz 848fe56b9e6SYuval Mintz timeset = p_hwfn->cdev->tx_coalesce_usecs >> 849fe56b9e6SYuval Mintz (QED_CAU_DEF_TX_TIMER_RES + 1); 850fe56b9e6SYuval Mintz 851fe56b9e6SYuval Mintz for (i = 0; i < num_tc; i++) { 852fe56b9e6SYuval Mintz qed_int_cau_conf_pi(p_hwfn, p_ptt, 853fe56b9e6SYuval Mintz igu_sb_id, TX_PI(i), 854fe56b9e6SYuval Mintz QED_COAL_TX_STATE_MACHINE, 855fe56b9e6SYuval Mintz timeset); 856fe56b9e6SYuval Mintz } 857fe56b9e6SYuval Mintz } 858fe56b9e6SYuval Mintz } 859fe56b9e6SYuval Mintz 860fe56b9e6SYuval Mintz void qed_int_cau_conf_pi(struct qed_hwfn *p_hwfn, 861fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 862fe56b9e6SYuval Mintz u16 igu_sb_id, 863fe56b9e6SYuval Mintz u32 pi_index, 864fe56b9e6SYuval Mintz enum qed_coalescing_fsm coalescing_fsm, 865fe56b9e6SYuval Mintz u8 timeset) 866fe56b9e6SYuval Mintz { 867fe56b9e6SYuval Mintz struct cau_pi_entry pi_entry; 868fe56b9e6SYuval Mintz u32 sb_offset; 869fe56b9e6SYuval Mintz u32 pi_offset; 870fe56b9e6SYuval Mintz 871fe56b9e6SYuval Mintz sb_offset = igu_sb_id * PIS_PER_SB; 872fe56b9e6SYuval Mintz memset(&pi_entry, 0, sizeof(struct cau_pi_entry)); 873fe56b9e6SYuval Mintz 874fe56b9e6SYuval Mintz SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_PI_TIMESET, timeset); 875fe56b9e6SYuval Mintz if (coalescing_fsm == QED_COAL_RX_STATE_MACHINE) 876fe56b9e6SYuval Mintz SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_FSM_SEL, 0); 877fe56b9e6SYuval Mintz else 878fe56b9e6SYuval Mintz SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_FSM_SEL, 1); 879fe56b9e6SYuval Mintz 880fe56b9e6SYuval Mintz pi_offset = sb_offset + pi_index; 881fe56b9e6SYuval Mintz if (p_hwfn->hw_init_done) { 882fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, 883fe56b9e6SYuval Mintz CAU_REG_PI_MEMORY + pi_offset * sizeof(u32), 884fe56b9e6SYuval Mintz *((u32 *)&(pi_entry))); 885fe56b9e6SYuval Mintz } else { 886fe56b9e6SYuval Mintz STORE_RT_REG(p_hwfn, 887fe56b9e6SYuval Mintz CAU_REG_PI_MEMORY_RT_OFFSET + pi_offset, 888fe56b9e6SYuval Mintz *((u32 *)&(pi_entry))); 889fe56b9e6SYuval Mintz } 890fe56b9e6SYuval Mintz } 891fe56b9e6SYuval Mintz 892fe56b9e6SYuval Mintz void qed_int_sb_setup(struct qed_hwfn *p_hwfn, 893fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 894fe56b9e6SYuval Mintz struct qed_sb_info *sb_info) 895fe56b9e6SYuval Mintz { 896fe56b9e6SYuval Mintz /* zero status block and ack counter */ 897fe56b9e6SYuval Mintz sb_info->sb_ack = 0; 898fe56b9e6SYuval Mintz memset(sb_info->sb_virt, 0, sizeof(*sb_info->sb_virt)); 899fe56b9e6SYuval Mintz 900fe56b9e6SYuval Mintz qed_int_cau_conf_sb(p_hwfn, p_ptt, sb_info->sb_phys, 901fe56b9e6SYuval Mintz sb_info->igu_sb_id, 0, 0); 902fe56b9e6SYuval Mintz } 903fe56b9e6SYuval Mintz 904fe56b9e6SYuval Mintz /** 905fe56b9e6SYuval Mintz * @brief qed_get_igu_sb_id - given a sw sb_id return the 906fe56b9e6SYuval Mintz * igu_sb_id 907fe56b9e6SYuval Mintz * 908fe56b9e6SYuval Mintz * @param p_hwfn 909fe56b9e6SYuval Mintz * @param sb_id 910fe56b9e6SYuval Mintz * 911fe56b9e6SYuval Mintz * @return u16 912fe56b9e6SYuval Mintz */ 913fe56b9e6SYuval Mintz static u16 qed_get_igu_sb_id(struct qed_hwfn *p_hwfn, 914fe56b9e6SYuval Mintz u16 sb_id) 915fe56b9e6SYuval Mintz { 916fe56b9e6SYuval Mintz u16 igu_sb_id; 917fe56b9e6SYuval Mintz 918fe56b9e6SYuval Mintz /* Assuming continuous set of IGU SBs dedicated for given PF */ 919fe56b9e6SYuval Mintz if (sb_id == QED_SP_SB_ID) 920fe56b9e6SYuval Mintz igu_sb_id = p_hwfn->hw_info.p_igu_info->igu_dsb_id; 921fe56b9e6SYuval Mintz else 922fe56b9e6SYuval Mintz igu_sb_id = sb_id + p_hwfn->hw_info.p_igu_info->igu_base_sb; 923fe56b9e6SYuval Mintz 924fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "SB [%s] index is 0x%04x\n", 925fe56b9e6SYuval Mintz (sb_id == QED_SP_SB_ID) ? "DSB" : "non-DSB", igu_sb_id); 926fe56b9e6SYuval Mintz 927fe56b9e6SYuval Mintz return igu_sb_id; 928fe56b9e6SYuval Mintz } 929fe56b9e6SYuval Mintz 930fe56b9e6SYuval Mintz int qed_int_sb_init(struct qed_hwfn *p_hwfn, 931fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 932fe56b9e6SYuval Mintz struct qed_sb_info *sb_info, 933fe56b9e6SYuval Mintz void *sb_virt_addr, 934fe56b9e6SYuval Mintz dma_addr_t sb_phy_addr, 935fe56b9e6SYuval Mintz u16 sb_id) 936fe56b9e6SYuval Mintz { 937fe56b9e6SYuval Mintz sb_info->sb_virt = sb_virt_addr; 938fe56b9e6SYuval Mintz sb_info->sb_phys = sb_phy_addr; 939fe56b9e6SYuval Mintz 940fe56b9e6SYuval Mintz sb_info->igu_sb_id = qed_get_igu_sb_id(p_hwfn, sb_id); 941fe56b9e6SYuval Mintz 942fe56b9e6SYuval Mintz if (sb_id != QED_SP_SB_ID) { 943fe56b9e6SYuval Mintz p_hwfn->sbs_info[sb_id] = sb_info; 944fe56b9e6SYuval Mintz p_hwfn->num_sbs++; 945fe56b9e6SYuval Mintz } 946fe56b9e6SYuval Mintz 947fe56b9e6SYuval Mintz sb_info->cdev = p_hwfn->cdev; 948fe56b9e6SYuval Mintz 949fe56b9e6SYuval Mintz /* The igu address will hold the absolute address that needs to be 950fe56b9e6SYuval Mintz * written to for a specific status block 951fe56b9e6SYuval Mintz */ 952fe56b9e6SYuval Mintz sb_info->igu_addr = (u8 __iomem *)p_hwfn->regview + 953fe56b9e6SYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 954fe56b9e6SYuval Mintz (sb_info->igu_sb_id << 3); 955fe56b9e6SYuval Mintz 956fe56b9e6SYuval Mintz sb_info->flags |= QED_SB_INFO_INIT; 957fe56b9e6SYuval Mintz 958fe56b9e6SYuval Mintz qed_int_sb_setup(p_hwfn, p_ptt, sb_info); 959fe56b9e6SYuval Mintz 960fe56b9e6SYuval Mintz return 0; 961fe56b9e6SYuval Mintz } 962fe56b9e6SYuval Mintz 963fe56b9e6SYuval Mintz int qed_int_sb_release(struct qed_hwfn *p_hwfn, 964fe56b9e6SYuval Mintz struct qed_sb_info *sb_info, 965fe56b9e6SYuval Mintz u16 sb_id) 966fe56b9e6SYuval Mintz { 967fe56b9e6SYuval Mintz if (sb_id == QED_SP_SB_ID) { 968fe56b9e6SYuval Mintz DP_ERR(p_hwfn, "Do Not free sp sb using this function"); 969fe56b9e6SYuval Mintz return -EINVAL; 970fe56b9e6SYuval Mintz } 971fe56b9e6SYuval Mintz 972fe56b9e6SYuval Mintz /* zero status block and ack counter */ 973fe56b9e6SYuval Mintz sb_info->sb_ack = 0; 974fe56b9e6SYuval Mintz memset(sb_info->sb_virt, 0, sizeof(*sb_info->sb_virt)); 975fe56b9e6SYuval Mintz 9764ac801b7SYuval Mintz if (p_hwfn->sbs_info[sb_id] != NULL) { 977fe56b9e6SYuval Mintz p_hwfn->sbs_info[sb_id] = NULL; 978fe56b9e6SYuval Mintz p_hwfn->num_sbs--; 9794ac801b7SYuval Mintz } 980fe56b9e6SYuval Mintz 981fe56b9e6SYuval Mintz return 0; 982fe56b9e6SYuval Mintz } 983fe56b9e6SYuval Mintz 984fe56b9e6SYuval Mintz static void qed_int_sp_sb_free(struct qed_hwfn *p_hwfn) 985fe56b9e6SYuval Mintz { 986fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sb = p_hwfn->p_sp_sb; 987fe56b9e6SYuval Mintz 9884ac801b7SYuval Mintz if (!p_sb) 9894ac801b7SYuval Mintz return; 9904ac801b7SYuval Mintz 991fe56b9e6SYuval Mintz if (p_sb->sb_info.sb_virt) 992fe56b9e6SYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 993fe56b9e6SYuval Mintz SB_ALIGNED_SIZE(p_hwfn), 994fe56b9e6SYuval Mintz p_sb->sb_info.sb_virt, 995fe56b9e6SYuval Mintz p_sb->sb_info.sb_phys); 996fe56b9e6SYuval Mintz kfree(p_sb); 997fe56b9e6SYuval Mintz } 998fe56b9e6SYuval Mintz 999fe56b9e6SYuval Mintz static int qed_int_sp_sb_alloc(struct qed_hwfn *p_hwfn, 1000fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 1001fe56b9e6SYuval Mintz { 1002fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sb; 1003fe56b9e6SYuval Mintz dma_addr_t p_phys = 0; 1004fe56b9e6SYuval Mintz void *p_virt; 1005fe56b9e6SYuval Mintz 1006fe56b9e6SYuval Mintz /* SB struct */ 100760fffb3bSYuval Mintz p_sb = kmalloc(sizeof(*p_sb), GFP_KERNEL); 1008fe56b9e6SYuval Mintz if (!p_sb) { 1009fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, "Failed to allocate `struct qed_sb_info'\n"); 1010fe56b9e6SYuval Mintz return -ENOMEM; 1011fe56b9e6SYuval Mintz } 1012fe56b9e6SYuval Mintz 1013fe56b9e6SYuval Mintz /* SB ring */ 1014fe56b9e6SYuval Mintz p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 1015fe56b9e6SYuval Mintz SB_ALIGNED_SIZE(p_hwfn), 1016fe56b9e6SYuval Mintz &p_phys, GFP_KERNEL); 1017fe56b9e6SYuval Mintz if (!p_virt) { 1018fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, "Failed to allocate status block\n"); 1019fe56b9e6SYuval Mintz kfree(p_sb); 1020fe56b9e6SYuval Mintz return -ENOMEM; 1021fe56b9e6SYuval Mintz } 1022fe56b9e6SYuval Mintz 1023fe56b9e6SYuval Mintz /* Status Block setup */ 1024fe56b9e6SYuval Mintz p_hwfn->p_sp_sb = p_sb; 1025fe56b9e6SYuval Mintz qed_int_sb_init(p_hwfn, p_ptt, &p_sb->sb_info, p_virt, 1026fe56b9e6SYuval Mintz p_phys, QED_SP_SB_ID); 1027fe56b9e6SYuval Mintz 1028fe56b9e6SYuval Mintz memset(p_sb->pi_info_arr, 0, sizeof(p_sb->pi_info_arr)); 1029fe56b9e6SYuval Mintz 1030fe56b9e6SYuval Mintz return 0; 1031fe56b9e6SYuval Mintz } 1032fe56b9e6SYuval Mintz 1033fe56b9e6SYuval Mintz int qed_int_register_cb(struct qed_hwfn *p_hwfn, 1034fe56b9e6SYuval Mintz qed_int_comp_cb_t comp_cb, 1035fe56b9e6SYuval Mintz void *cookie, 1036fe56b9e6SYuval Mintz u8 *sb_idx, 1037fe56b9e6SYuval Mintz __le16 **p_fw_cons) 1038fe56b9e6SYuval Mintz { 1039fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sp_sb = p_hwfn->p_sp_sb; 10404ac801b7SYuval Mintz int rc = -ENOMEM; 1041fe56b9e6SYuval Mintz u8 pi; 1042fe56b9e6SYuval Mintz 1043fe56b9e6SYuval Mintz /* Look for a free index */ 1044fe56b9e6SYuval Mintz for (pi = 0; pi < ARRAY_SIZE(p_sp_sb->pi_info_arr); pi++) { 10454ac801b7SYuval Mintz if (p_sp_sb->pi_info_arr[pi].comp_cb) 10464ac801b7SYuval Mintz continue; 10474ac801b7SYuval Mintz 1048fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].comp_cb = comp_cb; 1049fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].cookie = cookie; 1050fe56b9e6SYuval Mintz *sb_idx = pi; 1051fe56b9e6SYuval Mintz *p_fw_cons = &p_sp_sb->sb_info.sb_virt->pi_array[pi]; 10524ac801b7SYuval Mintz rc = 0; 1053fe56b9e6SYuval Mintz break; 1054fe56b9e6SYuval Mintz } 1055fe56b9e6SYuval Mintz 10564ac801b7SYuval Mintz return rc; 1057fe56b9e6SYuval Mintz } 1058fe56b9e6SYuval Mintz 1059fe56b9e6SYuval Mintz int qed_int_unregister_cb(struct qed_hwfn *p_hwfn, u8 pi) 1060fe56b9e6SYuval Mintz { 1061fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sp_sb = p_hwfn->p_sp_sb; 1062fe56b9e6SYuval Mintz 10634ac801b7SYuval Mintz if (p_sp_sb->pi_info_arr[pi].comp_cb == NULL) 10644ac801b7SYuval Mintz return -ENOMEM; 10654ac801b7SYuval Mintz 1066fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].comp_cb = NULL; 1067fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].cookie = NULL; 1068fe56b9e6SYuval Mintz 10694ac801b7SYuval Mintz return 0; 1070fe56b9e6SYuval Mintz } 1071fe56b9e6SYuval Mintz 1072fe56b9e6SYuval Mintz u16 qed_int_get_sp_sb_id(struct qed_hwfn *p_hwfn) 1073fe56b9e6SYuval Mintz { 1074fe56b9e6SYuval Mintz return p_hwfn->p_sp_sb->sb_info.igu_sb_id; 1075fe56b9e6SYuval Mintz } 1076fe56b9e6SYuval Mintz 1077fe56b9e6SYuval Mintz void qed_int_igu_enable_int(struct qed_hwfn *p_hwfn, 1078fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 1079fe56b9e6SYuval Mintz enum qed_int_mode int_mode) 1080fe56b9e6SYuval Mintz { 1081cc875c2eSYuval Mintz u32 igu_pf_conf = IGU_PF_CONF_FUNC_EN | IGU_PF_CONF_ATTN_BIT_EN; 1082fe56b9e6SYuval Mintz 1083fe56b9e6SYuval Mintz p_hwfn->cdev->int_mode = int_mode; 1084fe56b9e6SYuval Mintz switch (p_hwfn->cdev->int_mode) { 1085fe56b9e6SYuval Mintz case QED_INT_MODE_INTA: 1086fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_INT_LINE_EN; 1087fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_SINGLE_ISR_EN; 1088fe56b9e6SYuval Mintz break; 1089fe56b9e6SYuval Mintz 1090fe56b9e6SYuval Mintz case QED_INT_MODE_MSI: 1091fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_MSI_MSIX_EN; 1092fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_SINGLE_ISR_EN; 1093fe56b9e6SYuval Mintz break; 1094fe56b9e6SYuval Mintz 1095fe56b9e6SYuval Mintz case QED_INT_MODE_MSIX: 1096fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_MSI_MSIX_EN; 1097fe56b9e6SYuval Mintz break; 1098fe56b9e6SYuval Mintz case QED_INT_MODE_POLL: 1099fe56b9e6SYuval Mintz break; 1100fe56b9e6SYuval Mintz } 1101fe56b9e6SYuval Mintz 1102fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_PF_CONFIGURATION, igu_pf_conf); 1103fe56b9e6SYuval Mintz } 1104fe56b9e6SYuval Mintz 11058f16bc97SSudarsana Kalluru int qed_int_igu_enable(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, 1106fe56b9e6SYuval Mintz enum qed_int_mode int_mode) 1107fe56b9e6SYuval Mintz { 11080d956e8aSYuval Mintz int rc; 1109fe56b9e6SYuval Mintz 11100d956e8aSYuval Mintz /* Configure AEU signal change to produce attentions */ 11110d956e8aSYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_ATTENTION_ENABLE, 0); 1112cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_LEADING_EDGE_LATCH, 0xfff); 1113cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_TRAILING_EDGE_LATCH, 0xfff); 11140d956e8aSYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_ATTENTION_ENABLE, 0xfff); 1115cc875c2eSYuval Mintz 1116fe56b9e6SYuval Mintz /* Flush the writes to IGU */ 1117fe56b9e6SYuval Mintz mmiowb(); 1118cc875c2eSYuval Mintz 1119cc875c2eSYuval Mintz /* Unmask AEU signals toward IGU */ 1120cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, MISC_REG_AEU_MASK_ATTN_IGU, 0xff); 11218f16bc97SSudarsana Kalluru if ((int_mode != QED_INT_MODE_INTA) || IS_LEAD_HWFN(p_hwfn)) { 11228f16bc97SSudarsana Kalluru rc = qed_slowpath_irq_req(p_hwfn); 11238f16bc97SSudarsana Kalluru if (rc != 0) { 11248f16bc97SSudarsana Kalluru DP_NOTICE(p_hwfn, "Slowpath IRQ request failed\n"); 11258f16bc97SSudarsana Kalluru return -EINVAL; 11268f16bc97SSudarsana Kalluru } 11278f16bc97SSudarsana Kalluru p_hwfn->b_int_requested = true; 11288f16bc97SSudarsana Kalluru } 11298f16bc97SSudarsana Kalluru /* Enable interrupt Generation */ 11308f16bc97SSudarsana Kalluru qed_int_igu_enable_int(p_hwfn, p_ptt, int_mode); 11318f16bc97SSudarsana Kalluru p_hwfn->b_int_enabled = 1; 11328f16bc97SSudarsana Kalluru 11338f16bc97SSudarsana Kalluru return rc; 1134fe56b9e6SYuval Mintz } 1135fe56b9e6SYuval Mintz 1136fe56b9e6SYuval Mintz void qed_int_igu_disable_int(struct qed_hwfn *p_hwfn, 1137fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 1138fe56b9e6SYuval Mintz { 1139fe56b9e6SYuval Mintz p_hwfn->b_int_enabled = 0; 1140fe56b9e6SYuval Mintz 1141fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_PF_CONFIGURATION, 0); 1142fe56b9e6SYuval Mintz } 1143fe56b9e6SYuval Mintz 1144fe56b9e6SYuval Mintz #define IGU_CLEANUP_SLEEP_LENGTH (1000) 1145fe56b9e6SYuval Mintz void qed_int_igu_cleanup_sb(struct qed_hwfn *p_hwfn, 1146fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 1147fe56b9e6SYuval Mintz u32 sb_id, 1148fe56b9e6SYuval Mintz bool cleanup_set, 1149fe56b9e6SYuval Mintz u16 opaque_fid 1150fe56b9e6SYuval Mintz ) 1151fe56b9e6SYuval Mintz { 1152fe56b9e6SYuval Mintz u32 pxp_addr = IGU_CMD_INT_ACK_BASE + sb_id; 1153fe56b9e6SYuval Mintz u32 sleep_cnt = IGU_CLEANUP_SLEEP_LENGTH; 1154fe56b9e6SYuval Mintz u32 data = 0; 1155fe56b9e6SYuval Mintz u32 cmd_ctrl = 0; 1156fe56b9e6SYuval Mintz u32 val = 0; 1157fe56b9e6SYuval Mintz u32 sb_bit = 0; 1158fe56b9e6SYuval Mintz u32 sb_bit_addr = 0; 1159fe56b9e6SYuval Mintz 1160fe56b9e6SYuval Mintz /* Set the data field */ 1161fe56b9e6SYuval Mintz SET_FIELD(data, IGU_CLEANUP_CLEANUP_SET, cleanup_set ? 1 : 0); 1162fe56b9e6SYuval Mintz SET_FIELD(data, IGU_CLEANUP_CLEANUP_TYPE, 0); 1163fe56b9e6SYuval Mintz SET_FIELD(data, IGU_CLEANUP_COMMAND_TYPE, IGU_COMMAND_TYPE_SET); 1164fe56b9e6SYuval Mintz 1165fe56b9e6SYuval Mintz /* Set the control register */ 1166fe56b9e6SYuval Mintz SET_FIELD(cmd_ctrl, IGU_CTRL_REG_PXP_ADDR, pxp_addr); 1167fe56b9e6SYuval Mintz SET_FIELD(cmd_ctrl, IGU_CTRL_REG_FID, opaque_fid); 1168fe56b9e6SYuval Mintz SET_FIELD(cmd_ctrl, IGU_CTRL_REG_TYPE, IGU_CTRL_CMD_TYPE_WR); 1169fe56b9e6SYuval Mintz 1170fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_COMMAND_REG_32LSB_DATA, data); 1171fe56b9e6SYuval Mintz 1172fe56b9e6SYuval Mintz barrier(); 1173fe56b9e6SYuval Mintz 1174fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_COMMAND_REG_CTRL, cmd_ctrl); 1175fe56b9e6SYuval Mintz 1176fe56b9e6SYuval Mintz /* Flush the write to IGU */ 1177fe56b9e6SYuval Mintz mmiowb(); 1178fe56b9e6SYuval Mintz 1179fe56b9e6SYuval Mintz /* calculate where to read the status bit from */ 1180fe56b9e6SYuval Mintz sb_bit = 1 << (sb_id % 32); 1181fe56b9e6SYuval Mintz sb_bit_addr = sb_id / 32 * sizeof(u32); 1182fe56b9e6SYuval Mintz 1183fe56b9e6SYuval Mintz sb_bit_addr += IGU_REG_CLEANUP_STATUS_0; 1184fe56b9e6SYuval Mintz 1185fe56b9e6SYuval Mintz /* Now wait for the command to complete */ 1186fe56b9e6SYuval Mintz do { 1187fe56b9e6SYuval Mintz val = qed_rd(p_hwfn, p_ptt, sb_bit_addr); 1188fe56b9e6SYuval Mintz 1189fe56b9e6SYuval Mintz if ((val & sb_bit) == (cleanup_set ? sb_bit : 0)) 1190fe56b9e6SYuval Mintz break; 1191fe56b9e6SYuval Mintz 1192fe56b9e6SYuval Mintz usleep_range(5000, 10000); 1193fe56b9e6SYuval Mintz } while (--sleep_cnt); 1194fe56b9e6SYuval Mintz 1195fe56b9e6SYuval Mintz if (!sleep_cnt) 1196fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, 1197fe56b9e6SYuval Mintz "Timeout waiting for clear status 0x%08x [for sb %d]\n", 1198fe56b9e6SYuval Mintz val, sb_id); 1199fe56b9e6SYuval Mintz } 1200fe56b9e6SYuval Mintz 1201fe56b9e6SYuval Mintz void qed_int_igu_init_pure_rt_single(struct qed_hwfn *p_hwfn, 1202fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 1203fe56b9e6SYuval Mintz u32 sb_id, 1204fe56b9e6SYuval Mintz u16 opaque, 1205fe56b9e6SYuval Mintz bool b_set) 1206fe56b9e6SYuval Mintz { 1207fe56b9e6SYuval Mintz int pi; 1208fe56b9e6SYuval Mintz 1209fe56b9e6SYuval Mintz /* Set */ 1210fe56b9e6SYuval Mintz if (b_set) 1211fe56b9e6SYuval Mintz qed_int_igu_cleanup_sb(p_hwfn, p_ptt, sb_id, 1, opaque); 1212fe56b9e6SYuval Mintz 1213fe56b9e6SYuval Mintz /* Clear */ 1214fe56b9e6SYuval Mintz qed_int_igu_cleanup_sb(p_hwfn, p_ptt, sb_id, 0, opaque); 1215fe56b9e6SYuval Mintz 1216fe56b9e6SYuval Mintz /* Clear the CAU for the SB */ 1217fe56b9e6SYuval Mintz for (pi = 0; pi < 12; pi++) 1218fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, 1219fe56b9e6SYuval Mintz CAU_REG_PI_MEMORY + (sb_id * 12 + pi) * 4, 0); 1220fe56b9e6SYuval Mintz } 1221fe56b9e6SYuval Mintz 1222fe56b9e6SYuval Mintz void qed_int_igu_init_pure_rt(struct qed_hwfn *p_hwfn, 1223fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 1224fe56b9e6SYuval Mintz bool b_set, 1225fe56b9e6SYuval Mintz bool b_slowpath) 1226fe56b9e6SYuval Mintz { 1227fe56b9e6SYuval Mintz u32 igu_base_sb = p_hwfn->hw_info.p_igu_info->igu_base_sb; 1228fe56b9e6SYuval Mintz u32 igu_sb_cnt = p_hwfn->hw_info.p_igu_info->igu_sb_cnt; 1229fe56b9e6SYuval Mintz u32 sb_id = 0; 1230fe56b9e6SYuval Mintz u32 val = 0; 1231fe56b9e6SYuval Mintz 1232fe56b9e6SYuval Mintz val = qed_rd(p_hwfn, p_ptt, IGU_REG_BLOCK_CONFIGURATION); 1233fe56b9e6SYuval Mintz val |= IGU_REG_BLOCK_CONFIGURATION_VF_CLEANUP_EN; 1234fe56b9e6SYuval Mintz val &= ~IGU_REG_BLOCK_CONFIGURATION_PXP_TPH_INTERFACE_EN; 1235fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_BLOCK_CONFIGURATION, val); 1236fe56b9e6SYuval Mintz 1237fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 1238fe56b9e6SYuval Mintz "IGU cleaning SBs [%d,...,%d]\n", 1239fe56b9e6SYuval Mintz igu_base_sb, igu_base_sb + igu_sb_cnt - 1); 1240fe56b9e6SYuval Mintz 1241fe56b9e6SYuval Mintz for (sb_id = igu_base_sb; sb_id < igu_base_sb + igu_sb_cnt; sb_id++) 1242fe56b9e6SYuval Mintz qed_int_igu_init_pure_rt_single(p_hwfn, p_ptt, sb_id, 1243fe56b9e6SYuval Mintz p_hwfn->hw_info.opaque_fid, 1244fe56b9e6SYuval Mintz b_set); 1245fe56b9e6SYuval Mintz 1246fe56b9e6SYuval Mintz if (b_slowpath) { 1247fe56b9e6SYuval Mintz sb_id = p_hwfn->hw_info.p_igu_info->igu_dsb_id; 1248fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 1249fe56b9e6SYuval Mintz "IGU cleaning slowpath SB [%d]\n", sb_id); 1250fe56b9e6SYuval Mintz qed_int_igu_init_pure_rt_single(p_hwfn, p_ptt, sb_id, 1251fe56b9e6SYuval Mintz p_hwfn->hw_info.opaque_fid, 1252fe56b9e6SYuval Mintz b_set); 1253fe56b9e6SYuval Mintz } 1254fe56b9e6SYuval Mintz } 1255fe56b9e6SYuval Mintz 12564ac801b7SYuval Mintz static u32 qed_int_igu_read_cam_block(struct qed_hwfn *p_hwfn, 12574ac801b7SYuval Mintz struct qed_ptt *p_ptt, 12584ac801b7SYuval Mintz u16 sb_id) 12594ac801b7SYuval Mintz { 12604ac801b7SYuval Mintz u32 val = qed_rd(p_hwfn, p_ptt, 12614ac801b7SYuval Mintz IGU_REG_MAPPING_MEMORY + 12624ac801b7SYuval Mintz sizeof(u32) * sb_id); 12634ac801b7SYuval Mintz struct qed_igu_block *p_block; 12644ac801b7SYuval Mintz 12654ac801b7SYuval Mintz p_block = &p_hwfn->hw_info.p_igu_info->igu_map.igu_blocks[sb_id]; 12664ac801b7SYuval Mintz 12674ac801b7SYuval Mintz /* stop scanning when hit first invalid PF entry */ 12684ac801b7SYuval Mintz if (!GET_FIELD(val, IGU_MAPPING_LINE_VALID) && 12694ac801b7SYuval Mintz GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID)) 12704ac801b7SYuval Mintz goto out; 12714ac801b7SYuval Mintz 12724ac801b7SYuval Mintz /* Fill the block information */ 12734ac801b7SYuval Mintz p_block->status = QED_IGU_STATUS_VALID; 12744ac801b7SYuval Mintz p_block->function_id = GET_FIELD(val, 12754ac801b7SYuval Mintz IGU_MAPPING_LINE_FUNCTION_NUMBER); 12764ac801b7SYuval Mintz p_block->is_pf = GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID); 12774ac801b7SYuval Mintz p_block->vector_number = GET_FIELD(val, 12784ac801b7SYuval Mintz IGU_MAPPING_LINE_VECTOR_NUMBER); 12794ac801b7SYuval Mintz 12804ac801b7SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 12814ac801b7SYuval Mintz "IGU_BLOCK: [SB 0x%04x, Value in CAM 0x%08x] func_id = %d is_pf = %d vector_num = 0x%x\n", 12824ac801b7SYuval Mintz sb_id, val, p_block->function_id, 12834ac801b7SYuval Mintz p_block->is_pf, p_block->vector_number); 12844ac801b7SYuval Mintz 12854ac801b7SYuval Mintz out: 12864ac801b7SYuval Mintz return val; 12874ac801b7SYuval Mintz } 12884ac801b7SYuval Mintz 1289fe56b9e6SYuval Mintz int qed_int_igu_read_cam(struct qed_hwfn *p_hwfn, 1290fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 1291fe56b9e6SYuval Mintz { 1292fe56b9e6SYuval Mintz struct qed_igu_info *p_igu_info; 1293fe56b9e6SYuval Mintz struct qed_igu_block *blk; 1294fe56b9e6SYuval Mintz u32 val; 1295fe56b9e6SYuval Mintz u16 sb_id; 1296fe56b9e6SYuval Mintz u16 prev_sb_id = 0xFF; 1297fe56b9e6SYuval Mintz 129860fffb3bSYuval Mintz p_hwfn->hw_info.p_igu_info = kzalloc(sizeof(*p_igu_info), GFP_KERNEL); 1299fe56b9e6SYuval Mintz 1300fe56b9e6SYuval Mintz if (!p_hwfn->hw_info.p_igu_info) 1301fe56b9e6SYuval Mintz return -ENOMEM; 1302fe56b9e6SYuval Mintz 1303fe56b9e6SYuval Mintz p_igu_info = p_hwfn->hw_info.p_igu_info; 1304fe56b9e6SYuval Mintz 1305fe56b9e6SYuval Mintz /* Initialize base sb / sb cnt for PFs */ 1306fe56b9e6SYuval Mintz p_igu_info->igu_base_sb = 0xffff; 1307fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt = 0; 1308fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id = 0xffff; 1309fe56b9e6SYuval Mintz p_igu_info->igu_base_sb_iov = 0xffff; 1310fe56b9e6SYuval Mintz 1311fe56b9e6SYuval Mintz for (sb_id = 0; sb_id < QED_MAPPING_MEMORY_SIZE(p_hwfn->cdev); 1312fe56b9e6SYuval Mintz sb_id++) { 1313fe56b9e6SYuval Mintz blk = &p_igu_info->igu_map.igu_blocks[sb_id]; 1314fe56b9e6SYuval Mintz 13154ac801b7SYuval Mintz val = qed_int_igu_read_cam_block(p_hwfn, p_ptt, sb_id); 1316fe56b9e6SYuval Mintz 1317fe56b9e6SYuval Mintz /* stop scanning when hit first invalid PF entry */ 1318fe56b9e6SYuval Mintz if (!GET_FIELD(val, IGU_MAPPING_LINE_VALID) && 1319fe56b9e6SYuval Mintz GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID)) 1320fe56b9e6SYuval Mintz break; 1321fe56b9e6SYuval Mintz 1322fe56b9e6SYuval Mintz if (blk->is_pf) { 1323fe56b9e6SYuval Mintz if (blk->function_id == p_hwfn->rel_pf_id) { 1324fe56b9e6SYuval Mintz blk->status |= QED_IGU_STATUS_PF; 1325fe56b9e6SYuval Mintz 1326fe56b9e6SYuval Mintz if (blk->vector_number == 0) { 1327fe56b9e6SYuval Mintz if (p_igu_info->igu_dsb_id == 0xffff) 1328fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id = sb_id; 1329fe56b9e6SYuval Mintz } else { 1330fe56b9e6SYuval Mintz if (p_igu_info->igu_base_sb == 1331fe56b9e6SYuval Mintz 0xffff) { 1332fe56b9e6SYuval Mintz p_igu_info->igu_base_sb = sb_id; 1333fe56b9e6SYuval Mintz } else if (prev_sb_id != sb_id - 1) { 1334fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn->cdev, 1335fe56b9e6SYuval Mintz "consecutive igu vectors for HWFN %x broken", 1336fe56b9e6SYuval Mintz p_hwfn->rel_pf_id); 1337fe56b9e6SYuval Mintz break; 1338fe56b9e6SYuval Mintz } 1339fe56b9e6SYuval Mintz prev_sb_id = sb_id; 1340fe56b9e6SYuval Mintz /* we don't count the default */ 1341fe56b9e6SYuval Mintz (p_igu_info->igu_sb_cnt)++; 1342fe56b9e6SYuval Mintz } 1343fe56b9e6SYuval Mintz } 1344fe56b9e6SYuval Mintz } 1345fe56b9e6SYuval Mintz } 1346fe56b9e6SYuval Mintz 1347fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 1348fe56b9e6SYuval Mintz "IGU igu_base_sb=0x%x igu_sb_cnt=%d igu_dsb_id=0x%x\n", 1349fe56b9e6SYuval Mintz p_igu_info->igu_base_sb, 1350fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt, 1351fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id); 1352fe56b9e6SYuval Mintz 1353fe56b9e6SYuval Mintz if (p_igu_info->igu_base_sb == 0xffff || 1354fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id == 0xffff || 1355fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt == 0) { 1356fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, 1357fe56b9e6SYuval Mintz "IGU CAM returned invalid values igu_base_sb=0x%x igu_sb_cnt=%d igu_dsb_id=0x%x\n", 1358fe56b9e6SYuval Mintz p_igu_info->igu_base_sb, 1359fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt, 1360fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id); 1361fe56b9e6SYuval Mintz return -EINVAL; 1362fe56b9e6SYuval Mintz } 1363fe56b9e6SYuval Mintz 1364fe56b9e6SYuval Mintz return 0; 1365fe56b9e6SYuval Mintz } 1366fe56b9e6SYuval Mintz 1367fe56b9e6SYuval Mintz /** 1368fe56b9e6SYuval Mintz * @brief Initialize igu runtime registers 1369fe56b9e6SYuval Mintz * 1370fe56b9e6SYuval Mintz * @param p_hwfn 1371fe56b9e6SYuval Mintz */ 1372fe56b9e6SYuval Mintz void qed_int_igu_init_rt(struct qed_hwfn *p_hwfn) 1373fe56b9e6SYuval Mintz { 1374fe56b9e6SYuval Mintz u32 igu_pf_conf = 0; 1375fe56b9e6SYuval Mintz 1376fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_FUNC_EN; 1377fe56b9e6SYuval Mintz 1378fe56b9e6SYuval Mintz STORE_RT_REG(p_hwfn, IGU_REG_PF_CONFIGURATION_RT_OFFSET, igu_pf_conf); 1379fe56b9e6SYuval Mintz } 1380fe56b9e6SYuval Mintz 1381fe56b9e6SYuval Mintz u64 qed_int_igu_read_sisr_reg(struct qed_hwfn *p_hwfn) 1382fe56b9e6SYuval Mintz { 1383fe56b9e6SYuval Mintz u64 intr_status = 0; 1384fe56b9e6SYuval Mintz u32 intr_status_lo = 0; 1385fe56b9e6SYuval Mintz u32 intr_status_hi = 0; 1386fe56b9e6SYuval Mintz u32 lsb_igu_cmd_addr = IGU_REG_SISR_MDPC_WMASK_LSB_UPPER - 1387fe56b9e6SYuval Mintz IGU_CMD_INT_ACK_BASE; 1388fe56b9e6SYuval Mintz u32 msb_igu_cmd_addr = IGU_REG_SISR_MDPC_WMASK_MSB_UPPER - 1389fe56b9e6SYuval Mintz IGU_CMD_INT_ACK_BASE; 1390fe56b9e6SYuval Mintz 1391fe56b9e6SYuval Mintz intr_status_lo = REG_RD(p_hwfn, 1392fe56b9e6SYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 1393fe56b9e6SYuval Mintz lsb_igu_cmd_addr * 8); 1394fe56b9e6SYuval Mintz intr_status_hi = REG_RD(p_hwfn, 1395fe56b9e6SYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 1396fe56b9e6SYuval Mintz msb_igu_cmd_addr * 8); 1397fe56b9e6SYuval Mintz intr_status = ((u64)intr_status_hi << 32) + (u64)intr_status_lo; 1398fe56b9e6SYuval Mintz 1399fe56b9e6SYuval Mintz return intr_status; 1400fe56b9e6SYuval Mintz } 1401fe56b9e6SYuval Mintz 1402fe56b9e6SYuval Mintz static void qed_int_sp_dpc_setup(struct qed_hwfn *p_hwfn) 1403fe56b9e6SYuval Mintz { 1404fe56b9e6SYuval Mintz tasklet_init(p_hwfn->sp_dpc, 1405fe56b9e6SYuval Mintz qed_int_sp_dpc, (unsigned long)p_hwfn); 1406fe56b9e6SYuval Mintz p_hwfn->b_sp_dpc_enabled = true; 1407fe56b9e6SYuval Mintz } 1408fe56b9e6SYuval Mintz 1409fe56b9e6SYuval Mintz static int qed_int_sp_dpc_alloc(struct qed_hwfn *p_hwfn) 1410fe56b9e6SYuval Mintz { 141160fffb3bSYuval Mintz p_hwfn->sp_dpc = kmalloc(sizeof(*p_hwfn->sp_dpc), GFP_KERNEL); 1412fe56b9e6SYuval Mintz if (!p_hwfn->sp_dpc) 1413fe56b9e6SYuval Mintz return -ENOMEM; 1414fe56b9e6SYuval Mintz 1415fe56b9e6SYuval Mintz return 0; 1416fe56b9e6SYuval Mintz } 1417fe56b9e6SYuval Mintz 1418fe56b9e6SYuval Mintz static void qed_int_sp_dpc_free(struct qed_hwfn *p_hwfn) 1419fe56b9e6SYuval Mintz { 1420fe56b9e6SYuval Mintz kfree(p_hwfn->sp_dpc); 1421fe56b9e6SYuval Mintz } 1422fe56b9e6SYuval Mintz 1423fe56b9e6SYuval Mintz int qed_int_alloc(struct qed_hwfn *p_hwfn, 1424fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 1425fe56b9e6SYuval Mintz { 1426fe56b9e6SYuval Mintz int rc = 0; 1427fe56b9e6SYuval Mintz 1428fe56b9e6SYuval Mintz rc = qed_int_sp_dpc_alloc(p_hwfn); 1429fe56b9e6SYuval Mintz if (rc) { 1430fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, "Failed to allocate sp dpc mem\n"); 1431fe56b9e6SYuval Mintz return rc; 1432fe56b9e6SYuval Mintz } 1433fe56b9e6SYuval Mintz rc = qed_int_sp_sb_alloc(p_hwfn, p_ptt); 1434fe56b9e6SYuval Mintz if (rc) { 1435fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, "Failed to allocate sp sb mem\n"); 1436fe56b9e6SYuval Mintz return rc; 1437fe56b9e6SYuval Mintz } 1438cc875c2eSYuval Mintz rc = qed_int_sb_attn_alloc(p_hwfn, p_ptt); 1439cc875c2eSYuval Mintz if (rc) { 1440cc875c2eSYuval Mintz DP_ERR(p_hwfn->cdev, "Failed to allocate sb attn mem\n"); 1441cc875c2eSYuval Mintz return rc; 1442cc875c2eSYuval Mintz } 1443fe56b9e6SYuval Mintz return rc; 1444fe56b9e6SYuval Mintz } 1445fe56b9e6SYuval Mintz 1446fe56b9e6SYuval Mintz void qed_int_free(struct qed_hwfn *p_hwfn) 1447fe56b9e6SYuval Mintz { 1448fe56b9e6SYuval Mintz qed_int_sp_sb_free(p_hwfn); 1449cc875c2eSYuval Mintz qed_int_sb_attn_free(p_hwfn); 1450fe56b9e6SYuval Mintz qed_int_sp_dpc_free(p_hwfn); 1451fe56b9e6SYuval Mintz } 1452fe56b9e6SYuval Mintz 1453fe56b9e6SYuval Mintz void qed_int_setup(struct qed_hwfn *p_hwfn, 1454fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 1455fe56b9e6SYuval Mintz { 14560d956e8aSYuval Mintz qed_int_sb_setup(p_hwfn, p_ptt, &p_hwfn->p_sp_sb->sb_info); 14570d956e8aSYuval Mintz qed_int_sb_attn_setup(p_hwfn, p_ptt); 1458fe56b9e6SYuval Mintz qed_int_sp_dpc_setup(p_hwfn); 1459fe56b9e6SYuval Mintz } 1460fe56b9e6SYuval Mintz 14614ac801b7SYuval Mintz void qed_int_get_num_sbs(struct qed_hwfn *p_hwfn, 14624ac801b7SYuval Mintz struct qed_sb_cnt_info *p_sb_cnt_info) 1463fe56b9e6SYuval Mintz { 1464fe56b9e6SYuval Mintz struct qed_igu_info *info = p_hwfn->hw_info.p_igu_info; 1465fe56b9e6SYuval Mintz 14664ac801b7SYuval Mintz if (!info || !p_sb_cnt_info) 14674ac801b7SYuval Mintz return; 1468fe56b9e6SYuval Mintz 14694ac801b7SYuval Mintz p_sb_cnt_info->sb_cnt = info->igu_sb_cnt; 14704ac801b7SYuval Mintz p_sb_cnt_info->sb_iov_cnt = info->igu_sb_cnt_iov; 14714ac801b7SYuval Mintz p_sb_cnt_info->sb_free_blk = info->free_blks; 1472fe56b9e6SYuval Mintz } 14738f16bc97SSudarsana Kalluru 14748f16bc97SSudarsana Kalluru void qed_int_disable_post_isr_release(struct qed_dev *cdev) 14758f16bc97SSudarsana Kalluru { 14768f16bc97SSudarsana Kalluru int i; 14778f16bc97SSudarsana Kalluru 14788f16bc97SSudarsana Kalluru for_each_hwfn(cdev, i) 14798f16bc97SSudarsana Kalluru cdev->hwfns[i].b_int_requested = false; 14808f16bc97SSudarsana Kalluru } 1481