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 45cc875c2eSYuval Mintz #define ATTN_STATE_BITS (0xfff) 46cc875c2eSYuval Mintz #define ATTN_BITS_MASKABLE (0x3ff) 47cc875c2eSYuval Mintz struct qed_sb_attn_info { 48cc875c2eSYuval Mintz /* Virtual & Physical address of the SB */ 49cc875c2eSYuval Mintz struct atten_status_block *sb_attn; 50cc875c2eSYuval Mintz dma_addr_t sb_phys; 51cc875c2eSYuval Mintz 52cc875c2eSYuval Mintz /* Last seen running index */ 53cc875c2eSYuval Mintz u16 index; 54cc875c2eSYuval Mintz 55cc875c2eSYuval Mintz /* Previously asserted attentions, which are still unasserted */ 56cc875c2eSYuval Mintz u16 known_attn; 57cc875c2eSYuval Mintz 58cc875c2eSYuval Mintz /* Cleanup address for the link's general hw attention */ 59cc875c2eSYuval Mintz u32 mfw_attn_addr; 60cc875c2eSYuval Mintz }; 61cc875c2eSYuval Mintz 62cc875c2eSYuval Mintz static inline u16 qed_attn_update_idx(struct qed_hwfn *p_hwfn, 63cc875c2eSYuval Mintz struct qed_sb_attn_info *p_sb_desc) 64cc875c2eSYuval Mintz { 65cc875c2eSYuval Mintz u16 rc = 0; 66cc875c2eSYuval Mintz u16 index; 67cc875c2eSYuval Mintz 68cc875c2eSYuval Mintz /* Make certain HW write took affect */ 69cc875c2eSYuval Mintz mmiowb(); 70cc875c2eSYuval Mintz 71cc875c2eSYuval Mintz index = le16_to_cpu(p_sb_desc->sb_attn->sb_index); 72cc875c2eSYuval Mintz if (p_sb_desc->index != index) { 73cc875c2eSYuval Mintz p_sb_desc->index = index; 74cc875c2eSYuval Mintz rc = QED_SB_ATT_IDX; 75cc875c2eSYuval Mintz } 76cc875c2eSYuval Mintz 77cc875c2eSYuval Mintz /* Make certain we got a consistent view with HW */ 78cc875c2eSYuval Mintz mmiowb(); 79cc875c2eSYuval Mintz 80cc875c2eSYuval Mintz return rc; 81cc875c2eSYuval Mintz } 82cc875c2eSYuval Mintz 83cc875c2eSYuval Mintz /** 84cc875c2eSYuval Mintz * @brief qed_int_assertion - handles asserted attention bits 85cc875c2eSYuval Mintz * 86cc875c2eSYuval Mintz * @param p_hwfn 87cc875c2eSYuval Mintz * @param asserted_bits newly asserted bits 88cc875c2eSYuval Mintz * @return int 89cc875c2eSYuval Mintz */ 90cc875c2eSYuval Mintz static int qed_int_assertion(struct qed_hwfn *p_hwfn, 91cc875c2eSYuval Mintz u16 asserted_bits) 92cc875c2eSYuval Mintz { 93cc875c2eSYuval Mintz struct qed_sb_attn_info *sb_attn_sw = p_hwfn->p_sb_attn; 94cc875c2eSYuval Mintz u32 igu_mask; 95cc875c2eSYuval Mintz 96cc875c2eSYuval Mintz /* Mask the source of the attention in the IGU */ 97cc875c2eSYuval Mintz igu_mask = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, 98cc875c2eSYuval Mintz IGU_REG_ATTENTION_ENABLE); 99cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "IGU mask: 0x%08x --> 0x%08x\n", 100cc875c2eSYuval Mintz igu_mask, igu_mask & ~(asserted_bits & ATTN_BITS_MASKABLE)); 101cc875c2eSYuval Mintz igu_mask &= ~(asserted_bits & ATTN_BITS_MASKABLE); 102cc875c2eSYuval Mintz qed_wr(p_hwfn, p_hwfn->p_dpc_ptt, IGU_REG_ATTENTION_ENABLE, igu_mask); 103cc875c2eSYuval Mintz 104cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 105cc875c2eSYuval Mintz "inner known ATTN state: 0x%04x --> 0x%04x\n", 106cc875c2eSYuval Mintz sb_attn_sw->known_attn, 107cc875c2eSYuval Mintz sb_attn_sw->known_attn | asserted_bits); 108cc875c2eSYuval Mintz sb_attn_sw->known_attn |= asserted_bits; 109cc875c2eSYuval Mintz 110cc875c2eSYuval Mintz /* Handle MCP events */ 111cc875c2eSYuval Mintz if (asserted_bits & 0x100) { 112cc875c2eSYuval Mintz qed_mcp_handle_events(p_hwfn, p_hwfn->p_dpc_ptt); 113cc875c2eSYuval Mintz /* Clean the MCP attention */ 114cc875c2eSYuval Mintz qed_wr(p_hwfn, p_hwfn->p_dpc_ptt, 115cc875c2eSYuval Mintz sb_attn_sw->mfw_attn_addr, 0); 116cc875c2eSYuval Mintz } 117cc875c2eSYuval Mintz 118cc875c2eSYuval Mintz DIRECT_REG_WR((u8 __iomem *)p_hwfn->regview + 119cc875c2eSYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 120cc875c2eSYuval Mintz ((IGU_CMD_ATTN_BIT_SET_UPPER - 121cc875c2eSYuval Mintz IGU_CMD_INT_ACK_BASE) << 3), 122cc875c2eSYuval Mintz (u32)asserted_bits); 123cc875c2eSYuval Mintz 124cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "set cmd IGU: 0x%04x\n", 125cc875c2eSYuval Mintz asserted_bits); 126cc875c2eSYuval Mintz 127cc875c2eSYuval Mintz return 0; 128cc875c2eSYuval Mintz } 129cc875c2eSYuval Mintz 130cc875c2eSYuval Mintz /** 131cc875c2eSYuval Mintz * @brief - handles deassertion of previously asserted attentions. 132cc875c2eSYuval Mintz * 133cc875c2eSYuval Mintz * @param p_hwfn 134cc875c2eSYuval Mintz * @param deasserted_bits - newly deasserted bits 135cc875c2eSYuval Mintz * @return int 136cc875c2eSYuval Mintz * 137cc875c2eSYuval Mintz */ 138cc875c2eSYuval Mintz static int qed_int_deassertion(struct qed_hwfn *p_hwfn, 139cc875c2eSYuval Mintz u16 deasserted_bits) 140cc875c2eSYuval Mintz { 141cc875c2eSYuval Mintz struct qed_sb_attn_info *sb_attn_sw = p_hwfn->p_sb_attn; 142cc875c2eSYuval Mintz u32 aeu_mask; 143cc875c2eSYuval Mintz 144cc875c2eSYuval Mintz if (deasserted_bits != 0x100) 145cc875c2eSYuval Mintz DP_ERR(p_hwfn, "Unexpected - non-link deassertion\n"); 146cc875c2eSYuval Mintz 147cc875c2eSYuval Mintz /* Clear IGU indication for the deasserted bits */ 148cc875c2eSYuval Mintz DIRECT_REG_WR((u8 __iomem *)p_hwfn->regview + 149cc875c2eSYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 150cc875c2eSYuval Mintz ((IGU_CMD_ATTN_BIT_CLR_UPPER - 151cc875c2eSYuval Mintz IGU_CMD_INT_ACK_BASE) << 3), 152cc875c2eSYuval Mintz ~((u32)deasserted_bits)); 153cc875c2eSYuval Mintz 154cc875c2eSYuval Mintz /* Unmask deasserted attentions in IGU */ 155cc875c2eSYuval Mintz aeu_mask = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, 156cc875c2eSYuval Mintz IGU_REG_ATTENTION_ENABLE); 157cc875c2eSYuval Mintz aeu_mask |= (deasserted_bits & ATTN_BITS_MASKABLE); 158cc875c2eSYuval Mintz qed_wr(p_hwfn, p_hwfn->p_dpc_ptt, IGU_REG_ATTENTION_ENABLE, aeu_mask); 159cc875c2eSYuval Mintz 160cc875c2eSYuval Mintz /* Clear deassertion from inner state */ 161cc875c2eSYuval Mintz sb_attn_sw->known_attn &= ~deasserted_bits; 162cc875c2eSYuval Mintz 163cc875c2eSYuval Mintz return 0; 164cc875c2eSYuval Mintz } 165cc875c2eSYuval Mintz 166cc875c2eSYuval Mintz static int qed_int_attentions(struct qed_hwfn *p_hwfn) 167cc875c2eSYuval Mintz { 168cc875c2eSYuval Mintz struct qed_sb_attn_info *p_sb_attn_sw = p_hwfn->p_sb_attn; 169cc875c2eSYuval Mintz struct atten_status_block *p_sb_attn = p_sb_attn_sw->sb_attn; 170cc875c2eSYuval Mintz u32 attn_bits = 0, attn_acks = 0; 171cc875c2eSYuval Mintz u16 asserted_bits, deasserted_bits; 172cc875c2eSYuval Mintz __le16 index; 173cc875c2eSYuval Mintz int rc = 0; 174cc875c2eSYuval Mintz 175cc875c2eSYuval Mintz /* Read current attention bits/acks - safeguard against attentions 176cc875c2eSYuval Mintz * by guaranting work on a synchronized timeframe 177cc875c2eSYuval Mintz */ 178cc875c2eSYuval Mintz do { 179cc875c2eSYuval Mintz index = p_sb_attn->sb_index; 180cc875c2eSYuval Mintz attn_bits = le32_to_cpu(p_sb_attn->atten_bits); 181cc875c2eSYuval Mintz attn_acks = le32_to_cpu(p_sb_attn->atten_ack); 182cc875c2eSYuval Mintz } while (index != p_sb_attn->sb_index); 183cc875c2eSYuval Mintz p_sb_attn->sb_index = index; 184cc875c2eSYuval Mintz 185cc875c2eSYuval Mintz /* Attention / Deassertion are meaningful (and in correct state) 186cc875c2eSYuval Mintz * only when they differ and consistent with known state - deassertion 187cc875c2eSYuval Mintz * when previous attention & current ack, and assertion when current 188cc875c2eSYuval Mintz * attention with no previous attention 189cc875c2eSYuval Mintz */ 190cc875c2eSYuval Mintz asserted_bits = (attn_bits & ~attn_acks & ATTN_STATE_BITS) & 191cc875c2eSYuval Mintz ~p_sb_attn_sw->known_attn; 192cc875c2eSYuval Mintz deasserted_bits = (~attn_bits & attn_acks & ATTN_STATE_BITS) & 193cc875c2eSYuval Mintz p_sb_attn_sw->known_attn; 194cc875c2eSYuval Mintz 195cc875c2eSYuval Mintz if ((asserted_bits & ~0x100) || (deasserted_bits & ~0x100)) { 196cc875c2eSYuval Mintz DP_INFO(p_hwfn, 197cc875c2eSYuval Mintz "Attention: Index: 0x%04x, Bits: 0x%08x, Acks: 0x%08x, asserted: 0x%04x, De-asserted 0x%04x [Prev. known: 0x%04x]\n", 198cc875c2eSYuval Mintz index, attn_bits, attn_acks, asserted_bits, 199cc875c2eSYuval Mintz deasserted_bits, p_sb_attn_sw->known_attn); 200cc875c2eSYuval Mintz } else if (asserted_bits == 0x100) { 201cc875c2eSYuval Mintz DP_INFO(p_hwfn, 202cc875c2eSYuval Mintz "MFW indication via attention\n"); 203cc875c2eSYuval Mintz } else { 204cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 205cc875c2eSYuval Mintz "MFW indication [deassertion]\n"); 206cc875c2eSYuval Mintz } 207cc875c2eSYuval Mintz 208cc875c2eSYuval Mintz if (asserted_bits) { 209cc875c2eSYuval Mintz rc = qed_int_assertion(p_hwfn, asserted_bits); 210cc875c2eSYuval Mintz if (rc) 211cc875c2eSYuval Mintz return rc; 212cc875c2eSYuval Mintz } 213cc875c2eSYuval Mintz 214cc875c2eSYuval Mintz if (deasserted_bits) { 215cc875c2eSYuval Mintz rc = qed_int_deassertion(p_hwfn, deasserted_bits); 216cc875c2eSYuval Mintz if (rc) 217cc875c2eSYuval Mintz return rc; 218cc875c2eSYuval Mintz } 219cc875c2eSYuval Mintz 220cc875c2eSYuval Mintz return rc; 221cc875c2eSYuval Mintz } 222cc875c2eSYuval Mintz 223cc875c2eSYuval Mintz static void qed_sb_ack_attn(struct qed_hwfn *p_hwfn, 224cc875c2eSYuval Mintz void __iomem *igu_addr, 225cc875c2eSYuval Mintz u32 ack_cons) 226cc875c2eSYuval Mintz { 227cc875c2eSYuval Mintz struct igu_prod_cons_update igu_ack = { 0 }; 228cc875c2eSYuval Mintz 229cc875c2eSYuval Mintz igu_ack.sb_id_and_flags = 230cc875c2eSYuval Mintz ((ack_cons << IGU_PROD_CONS_UPDATE_SB_INDEX_SHIFT) | 231cc875c2eSYuval Mintz (1 << IGU_PROD_CONS_UPDATE_UPDATE_FLAG_SHIFT) | 232cc875c2eSYuval Mintz (IGU_INT_NOP << IGU_PROD_CONS_UPDATE_ENABLE_INT_SHIFT) | 233cc875c2eSYuval Mintz (IGU_SEG_ACCESS_ATTN << 234cc875c2eSYuval Mintz IGU_PROD_CONS_UPDATE_SEGMENT_ACCESS_SHIFT)); 235cc875c2eSYuval Mintz 236cc875c2eSYuval Mintz DIRECT_REG_WR(igu_addr, igu_ack.sb_id_and_flags); 237cc875c2eSYuval Mintz 238cc875c2eSYuval Mintz /* Both segments (interrupts & acks) are written to same place address; 239cc875c2eSYuval Mintz * Need to guarantee all commands will be received (in-order) by HW. 240cc875c2eSYuval Mintz */ 241cc875c2eSYuval Mintz mmiowb(); 242cc875c2eSYuval Mintz barrier(); 243cc875c2eSYuval Mintz } 244cc875c2eSYuval Mintz 245fe56b9e6SYuval Mintz void qed_int_sp_dpc(unsigned long hwfn_cookie) 246fe56b9e6SYuval Mintz { 247fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = (struct qed_hwfn *)hwfn_cookie; 248fe56b9e6SYuval Mintz struct qed_pi_info *pi_info = NULL; 249cc875c2eSYuval Mintz struct qed_sb_attn_info *sb_attn; 250fe56b9e6SYuval Mintz struct qed_sb_info *sb_info; 251fe56b9e6SYuval Mintz int arr_size; 252fe56b9e6SYuval Mintz u16 rc = 0; 253fe56b9e6SYuval Mintz 254fe56b9e6SYuval Mintz if (!p_hwfn->p_sp_sb) { 255fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, "DPC called - no p_sp_sb\n"); 256fe56b9e6SYuval Mintz return; 257fe56b9e6SYuval Mintz } 258fe56b9e6SYuval Mintz 259fe56b9e6SYuval Mintz sb_info = &p_hwfn->p_sp_sb->sb_info; 260fe56b9e6SYuval Mintz arr_size = ARRAY_SIZE(p_hwfn->p_sp_sb->pi_info_arr); 261fe56b9e6SYuval Mintz if (!sb_info) { 262fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, 263fe56b9e6SYuval Mintz "Status block is NULL - cannot ack interrupts\n"); 264fe56b9e6SYuval Mintz return; 265fe56b9e6SYuval Mintz } 266fe56b9e6SYuval Mintz 267cc875c2eSYuval Mintz if (!p_hwfn->p_sb_attn) { 268cc875c2eSYuval Mintz DP_ERR(p_hwfn->cdev, "DPC called - no p_sb_attn"); 269cc875c2eSYuval Mintz return; 270cc875c2eSYuval Mintz } 271cc875c2eSYuval Mintz sb_attn = p_hwfn->p_sb_attn; 272cc875c2eSYuval Mintz 273fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "DPC Called! (hwfn %p %d)\n", 274fe56b9e6SYuval Mintz p_hwfn, p_hwfn->my_id); 275fe56b9e6SYuval Mintz 276fe56b9e6SYuval Mintz /* Disable ack for def status block. Required both for msix + 277fe56b9e6SYuval Mintz * inta in non-mask mode, in inta does no harm. 278fe56b9e6SYuval Mintz */ 279fe56b9e6SYuval Mintz qed_sb_ack(sb_info, IGU_INT_DISABLE, 0); 280fe56b9e6SYuval Mintz 281fe56b9e6SYuval Mintz /* Gather Interrupts/Attentions information */ 282fe56b9e6SYuval Mintz if (!sb_info->sb_virt) { 283fe56b9e6SYuval Mintz DP_ERR( 284fe56b9e6SYuval Mintz p_hwfn->cdev, 285fe56b9e6SYuval Mintz "Interrupt Status block is NULL - cannot check for new interrupts!\n"); 286fe56b9e6SYuval Mintz } else { 287fe56b9e6SYuval Mintz u32 tmp_index = sb_info->sb_ack; 288fe56b9e6SYuval Mintz 289fe56b9e6SYuval Mintz rc = qed_sb_update_sb_idx(sb_info); 290fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn->cdev, NETIF_MSG_INTR, 291fe56b9e6SYuval Mintz "Interrupt indices: 0x%08x --> 0x%08x\n", 292fe56b9e6SYuval Mintz tmp_index, sb_info->sb_ack); 293fe56b9e6SYuval Mintz } 294fe56b9e6SYuval Mintz 295cc875c2eSYuval Mintz if (!sb_attn || !sb_attn->sb_attn) { 296cc875c2eSYuval Mintz DP_ERR( 297cc875c2eSYuval Mintz p_hwfn->cdev, 298cc875c2eSYuval Mintz "Attentions Status block is NULL - cannot check for new attentions!\n"); 299cc875c2eSYuval Mintz } else { 300cc875c2eSYuval Mintz u16 tmp_index = sb_attn->index; 301cc875c2eSYuval Mintz 302cc875c2eSYuval Mintz rc |= qed_attn_update_idx(p_hwfn, sb_attn); 303cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn->cdev, NETIF_MSG_INTR, 304cc875c2eSYuval Mintz "Attention indices: 0x%08x --> 0x%08x\n", 305cc875c2eSYuval Mintz tmp_index, sb_attn->index); 306cc875c2eSYuval Mintz } 307cc875c2eSYuval Mintz 308fe56b9e6SYuval Mintz /* Check if we expect interrupts at this time. if not just ack them */ 309fe56b9e6SYuval Mintz if (!(rc & QED_SB_EVENT_MASK)) { 310fe56b9e6SYuval Mintz qed_sb_ack(sb_info, IGU_INT_ENABLE, 1); 311fe56b9e6SYuval Mintz return; 312fe56b9e6SYuval Mintz } 313fe56b9e6SYuval Mintz 314fe56b9e6SYuval Mintz /* Check the validity of the DPC ptt. If not ack interrupts and fail */ 315fe56b9e6SYuval Mintz if (!p_hwfn->p_dpc_ptt) { 316fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn->cdev, "Failed to allocate PTT\n"); 317fe56b9e6SYuval Mintz qed_sb_ack(sb_info, IGU_INT_ENABLE, 1); 318fe56b9e6SYuval Mintz return; 319fe56b9e6SYuval Mintz } 320fe56b9e6SYuval Mintz 321cc875c2eSYuval Mintz if (rc & QED_SB_ATT_IDX) 322cc875c2eSYuval Mintz qed_int_attentions(p_hwfn); 323cc875c2eSYuval Mintz 324fe56b9e6SYuval Mintz if (rc & QED_SB_IDX) { 325fe56b9e6SYuval Mintz int pi; 326fe56b9e6SYuval Mintz 327fe56b9e6SYuval Mintz /* Look for a free index */ 328fe56b9e6SYuval Mintz for (pi = 0; pi < arr_size; pi++) { 329fe56b9e6SYuval Mintz pi_info = &p_hwfn->p_sp_sb->pi_info_arr[pi]; 330fe56b9e6SYuval Mintz if (pi_info->comp_cb) 331fe56b9e6SYuval Mintz pi_info->comp_cb(p_hwfn, pi_info->cookie); 332fe56b9e6SYuval Mintz } 333fe56b9e6SYuval Mintz } 334fe56b9e6SYuval Mintz 335cc875c2eSYuval Mintz if (sb_attn && (rc & QED_SB_ATT_IDX)) 336cc875c2eSYuval Mintz /* This should be done before the interrupts are enabled, 337cc875c2eSYuval Mintz * since otherwise a new attention will be generated. 338cc875c2eSYuval Mintz */ 339cc875c2eSYuval Mintz qed_sb_ack_attn(p_hwfn, sb_info->igu_addr, sb_attn->index); 340cc875c2eSYuval Mintz 341fe56b9e6SYuval Mintz qed_sb_ack(sb_info, IGU_INT_ENABLE, 1); 342fe56b9e6SYuval Mintz } 343fe56b9e6SYuval Mintz 344cc875c2eSYuval Mintz static void qed_int_sb_attn_free(struct qed_hwfn *p_hwfn) 345cc875c2eSYuval Mintz { 346cc875c2eSYuval Mintz struct qed_dev *cdev = p_hwfn->cdev; 347cc875c2eSYuval Mintz struct qed_sb_attn_info *p_sb = p_hwfn->p_sb_attn; 348cc875c2eSYuval Mintz 349cc875c2eSYuval Mintz if (p_sb) { 350cc875c2eSYuval Mintz if (p_sb->sb_attn) 351cc875c2eSYuval Mintz dma_free_coherent(&cdev->pdev->dev, 352cc875c2eSYuval Mintz SB_ATTN_ALIGNED_SIZE(p_hwfn), 353cc875c2eSYuval Mintz p_sb->sb_attn, 354cc875c2eSYuval Mintz p_sb->sb_phys); 355cc875c2eSYuval Mintz kfree(p_sb); 356cc875c2eSYuval Mintz } 357cc875c2eSYuval Mintz } 358cc875c2eSYuval Mintz 359cc875c2eSYuval Mintz static void qed_int_sb_attn_setup(struct qed_hwfn *p_hwfn, 360cc875c2eSYuval Mintz struct qed_ptt *p_ptt) 361cc875c2eSYuval Mintz { 362cc875c2eSYuval Mintz struct qed_sb_attn_info *sb_info = p_hwfn->p_sb_attn; 363cc875c2eSYuval Mintz 364cc875c2eSYuval Mintz memset(sb_info->sb_attn, 0, sizeof(*sb_info->sb_attn)); 365cc875c2eSYuval Mintz 366cc875c2eSYuval Mintz sb_info->index = 0; 367cc875c2eSYuval Mintz sb_info->known_attn = 0; 368cc875c2eSYuval Mintz 369cc875c2eSYuval Mintz /* Configure Attention Status Block in IGU */ 370cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_ATTN_MSG_ADDR_L, 371cc875c2eSYuval Mintz lower_32_bits(p_hwfn->p_sb_attn->sb_phys)); 372cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_ATTN_MSG_ADDR_H, 373cc875c2eSYuval Mintz upper_32_bits(p_hwfn->p_sb_attn->sb_phys)); 374cc875c2eSYuval Mintz } 375cc875c2eSYuval Mintz 376cc875c2eSYuval Mintz static void qed_int_sb_attn_init(struct qed_hwfn *p_hwfn, 377cc875c2eSYuval Mintz struct qed_ptt *p_ptt, 378cc875c2eSYuval Mintz void *sb_virt_addr, 379cc875c2eSYuval Mintz dma_addr_t sb_phy_addr) 380cc875c2eSYuval Mintz { 381cc875c2eSYuval Mintz struct qed_sb_attn_info *sb_info = p_hwfn->p_sb_attn; 382cc875c2eSYuval Mintz 383cc875c2eSYuval Mintz sb_info->sb_attn = sb_virt_addr; 384cc875c2eSYuval Mintz sb_info->sb_phys = sb_phy_addr; 385cc875c2eSYuval Mintz 386cc875c2eSYuval Mintz /* Set the address of cleanup for the mcp attention */ 387cc875c2eSYuval Mintz sb_info->mfw_attn_addr = (p_hwfn->rel_pf_id << 3) + 388cc875c2eSYuval Mintz MISC_REG_AEU_GENERAL_ATTN_0; 389cc875c2eSYuval Mintz 390cc875c2eSYuval Mintz qed_int_sb_attn_setup(p_hwfn, p_ptt); 391cc875c2eSYuval Mintz } 392cc875c2eSYuval Mintz 393cc875c2eSYuval Mintz static int qed_int_sb_attn_alloc(struct qed_hwfn *p_hwfn, 394cc875c2eSYuval Mintz struct qed_ptt *p_ptt) 395cc875c2eSYuval Mintz { 396cc875c2eSYuval Mintz struct qed_dev *cdev = p_hwfn->cdev; 397cc875c2eSYuval Mintz struct qed_sb_attn_info *p_sb; 398cc875c2eSYuval Mintz void *p_virt; 399cc875c2eSYuval Mintz dma_addr_t p_phys = 0; 400cc875c2eSYuval Mintz 401cc875c2eSYuval Mintz /* SB struct */ 40260fffb3bSYuval Mintz p_sb = kmalloc(sizeof(*p_sb), GFP_KERNEL); 403cc875c2eSYuval Mintz if (!p_sb) { 404cc875c2eSYuval Mintz DP_NOTICE(cdev, "Failed to allocate `struct qed_sb_attn_info'\n"); 405cc875c2eSYuval Mintz return -ENOMEM; 406cc875c2eSYuval Mintz } 407cc875c2eSYuval Mintz 408cc875c2eSYuval Mintz /* SB ring */ 409cc875c2eSYuval Mintz p_virt = dma_alloc_coherent(&cdev->pdev->dev, 410cc875c2eSYuval Mintz SB_ATTN_ALIGNED_SIZE(p_hwfn), 411cc875c2eSYuval Mintz &p_phys, GFP_KERNEL); 412cc875c2eSYuval Mintz 413cc875c2eSYuval Mintz if (!p_virt) { 414cc875c2eSYuval Mintz DP_NOTICE(cdev, "Failed to allocate status block (attentions)\n"); 415cc875c2eSYuval Mintz kfree(p_sb); 416cc875c2eSYuval Mintz return -ENOMEM; 417cc875c2eSYuval Mintz } 418cc875c2eSYuval Mintz 419cc875c2eSYuval Mintz /* Attention setup */ 420cc875c2eSYuval Mintz p_hwfn->p_sb_attn = p_sb; 421cc875c2eSYuval Mintz qed_int_sb_attn_init(p_hwfn, p_ptt, p_virt, p_phys); 422cc875c2eSYuval Mintz 423cc875c2eSYuval Mintz return 0; 424cc875c2eSYuval Mintz } 425cc875c2eSYuval Mintz 426fe56b9e6SYuval Mintz /* coalescing timeout = timeset << (timer_res + 1) */ 427fe56b9e6SYuval Mintz #define QED_CAU_DEF_RX_USECS 24 428fe56b9e6SYuval Mintz #define QED_CAU_DEF_TX_USECS 48 429fe56b9e6SYuval Mintz 430fe56b9e6SYuval Mintz void qed_init_cau_sb_entry(struct qed_hwfn *p_hwfn, 431fe56b9e6SYuval Mintz struct cau_sb_entry *p_sb_entry, 432fe56b9e6SYuval Mintz u8 pf_id, 433fe56b9e6SYuval Mintz u16 vf_number, 434fe56b9e6SYuval Mintz u8 vf_valid) 435fe56b9e6SYuval Mintz { 436fe56b9e6SYuval Mintz u32 cau_state; 437fe56b9e6SYuval Mintz 438fe56b9e6SYuval Mintz memset(p_sb_entry, 0, sizeof(*p_sb_entry)); 439fe56b9e6SYuval Mintz 440fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_PF_NUMBER, pf_id); 441fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_VF_NUMBER, vf_number); 442fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_VF_VALID, vf_valid); 443fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_SB_TIMESET0, 0x7F); 444fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_SB_TIMESET1, 0x7F); 445fe56b9e6SYuval Mintz 446fe56b9e6SYuval Mintz /* setting the time resultion to a fixed value ( = 1) */ 447fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_TIMER_RES0, 448fe56b9e6SYuval Mintz QED_CAU_DEF_RX_TIMER_RES); 449fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_TIMER_RES1, 450fe56b9e6SYuval Mintz QED_CAU_DEF_TX_TIMER_RES); 451fe56b9e6SYuval Mintz 452fe56b9e6SYuval Mintz cau_state = CAU_HC_DISABLE_STATE; 453fe56b9e6SYuval Mintz 454fe56b9e6SYuval Mintz if (p_hwfn->cdev->int_coalescing_mode == QED_COAL_MODE_ENABLE) { 455fe56b9e6SYuval Mintz cau_state = CAU_HC_ENABLE_STATE; 456fe56b9e6SYuval Mintz if (!p_hwfn->cdev->rx_coalesce_usecs) 457fe56b9e6SYuval Mintz p_hwfn->cdev->rx_coalesce_usecs = 458fe56b9e6SYuval Mintz QED_CAU_DEF_RX_USECS; 459fe56b9e6SYuval Mintz if (!p_hwfn->cdev->tx_coalesce_usecs) 460fe56b9e6SYuval Mintz p_hwfn->cdev->tx_coalesce_usecs = 461fe56b9e6SYuval Mintz QED_CAU_DEF_TX_USECS; 462fe56b9e6SYuval Mintz } 463fe56b9e6SYuval Mintz 464fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->data, CAU_SB_ENTRY_STATE0, cau_state); 465fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->data, CAU_SB_ENTRY_STATE1, cau_state); 466fe56b9e6SYuval Mintz } 467fe56b9e6SYuval Mintz 468fe56b9e6SYuval Mintz void qed_int_cau_conf_sb(struct qed_hwfn *p_hwfn, 469fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 470fe56b9e6SYuval Mintz dma_addr_t sb_phys, 471fe56b9e6SYuval Mintz u16 igu_sb_id, 472fe56b9e6SYuval Mintz u16 vf_number, 473fe56b9e6SYuval Mintz u8 vf_valid) 474fe56b9e6SYuval Mintz { 475fe56b9e6SYuval Mintz struct cau_sb_entry sb_entry; 476fe56b9e6SYuval Mintz u32 val; 477fe56b9e6SYuval Mintz 478fe56b9e6SYuval Mintz qed_init_cau_sb_entry(p_hwfn, &sb_entry, p_hwfn->rel_pf_id, 479fe56b9e6SYuval Mintz vf_number, vf_valid); 480fe56b9e6SYuval Mintz 481fe56b9e6SYuval Mintz if (p_hwfn->hw_init_done) { 482fe56b9e6SYuval Mintz val = CAU_REG_SB_ADDR_MEMORY + igu_sb_id * sizeof(u64); 483fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, val, lower_32_bits(sb_phys)); 484fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, val + sizeof(u32), 485fe56b9e6SYuval Mintz upper_32_bits(sb_phys)); 486fe56b9e6SYuval Mintz 487fe56b9e6SYuval Mintz val = CAU_REG_SB_VAR_MEMORY + igu_sb_id * sizeof(u64); 488fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, val, sb_entry.data); 489fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, val + sizeof(u32), sb_entry.params); 490fe56b9e6SYuval Mintz } else { 491fe56b9e6SYuval Mintz /* Initialize Status Block Address */ 492fe56b9e6SYuval Mintz STORE_RT_REG_AGG(p_hwfn, 493fe56b9e6SYuval Mintz CAU_REG_SB_ADDR_MEMORY_RT_OFFSET + 494fe56b9e6SYuval Mintz igu_sb_id * 2, 495fe56b9e6SYuval Mintz sb_phys); 496fe56b9e6SYuval Mintz 497fe56b9e6SYuval Mintz STORE_RT_REG_AGG(p_hwfn, 498fe56b9e6SYuval Mintz CAU_REG_SB_VAR_MEMORY_RT_OFFSET + 499fe56b9e6SYuval Mintz igu_sb_id * 2, 500fe56b9e6SYuval Mintz sb_entry); 501fe56b9e6SYuval Mintz } 502fe56b9e6SYuval Mintz 503fe56b9e6SYuval Mintz /* Configure pi coalescing if set */ 504fe56b9e6SYuval Mintz if (p_hwfn->cdev->int_coalescing_mode == QED_COAL_MODE_ENABLE) { 505fe56b9e6SYuval Mintz u8 timeset = p_hwfn->cdev->rx_coalesce_usecs >> 506fe56b9e6SYuval Mintz (QED_CAU_DEF_RX_TIMER_RES + 1); 507fe56b9e6SYuval Mintz u8 num_tc = 1, i; 508fe56b9e6SYuval Mintz 509fe56b9e6SYuval Mintz qed_int_cau_conf_pi(p_hwfn, p_ptt, igu_sb_id, RX_PI, 510fe56b9e6SYuval Mintz QED_COAL_RX_STATE_MACHINE, 511fe56b9e6SYuval Mintz timeset); 512fe56b9e6SYuval Mintz 513fe56b9e6SYuval Mintz timeset = p_hwfn->cdev->tx_coalesce_usecs >> 514fe56b9e6SYuval Mintz (QED_CAU_DEF_TX_TIMER_RES + 1); 515fe56b9e6SYuval Mintz 516fe56b9e6SYuval Mintz for (i = 0; i < num_tc; i++) { 517fe56b9e6SYuval Mintz qed_int_cau_conf_pi(p_hwfn, p_ptt, 518fe56b9e6SYuval Mintz igu_sb_id, TX_PI(i), 519fe56b9e6SYuval Mintz QED_COAL_TX_STATE_MACHINE, 520fe56b9e6SYuval Mintz timeset); 521fe56b9e6SYuval Mintz } 522fe56b9e6SYuval Mintz } 523fe56b9e6SYuval Mintz } 524fe56b9e6SYuval Mintz 525fe56b9e6SYuval Mintz void qed_int_cau_conf_pi(struct qed_hwfn *p_hwfn, 526fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 527fe56b9e6SYuval Mintz u16 igu_sb_id, 528fe56b9e6SYuval Mintz u32 pi_index, 529fe56b9e6SYuval Mintz enum qed_coalescing_fsm coalescing_fsm, 530fe56b9e6SYuval Mintz u8 timeset) 531fe56b9e6SYuval Mintz { 532fe56b9e6SYuval Mintz struct cau_pi_entry pi_entry; 533fe56b9e6SYuval Mintz u32 sb_offset; 534fe56b9e6SYuval Mintz u32 pi_offset; 535fe56b9e6SYuval Mintz 536fe56b9e6SYuval Mintz sb_offset = igu_sb_id * PIS_PER_SB; 537fe56b9e6SYuval Mintz memset(&pi_entry, 0, sizeof(struct cau_pi_entry)); 538fe56b9e6SYuval Mintz 539fe56b9e6SYuval Mintz SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_PI_TIMESET, timeset); 540fe56b9e6SYuval Mintz if (coalescing_fsm == QED_COAL_RX_STATE_MACHINE) 541fe56b9e6SYuval Mintz SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_FSM_SEL, 0); 542fe56b9e6SYuval Mintz else 543fe56b9e6SYuval Mintz SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_FSM_SEL, 1); 544fe56b9e6SYuval Mintz 545fe56b9e6SYuval Mintz pi_offset = sb_offset + pi_index; 546fe56b9e6SYuval Mintz if (p_hwfn->hw_init_done) { 547fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, 548fe56b9e6SYuval Mintz CAU_REG_PI_MEMORY + pi_offset * sizeof(u32), 549fe56b9e6SYuval Mintz *((u32 *)&(pi_entry))); 550fe56b9e6SYuval Mintz } else { 551fe56b9e6SYuval Mintz STORE_RT_REG(p_hwfn, 552fe56b9e6SYuval Mintz CAU_REG_PI_MEMORY_RT_OFFSET + pi_offset, 553fe56b9e6SYuval Mintz *((u32 *)&(pi_entry))); 554fe56b9e6SYuval Mintz } 555fe56b9e6SYuval Mintz } 556fe56b9e6SYuval Mintz 557fe56b9e6SYuval Mintz void qed_int_sb_setup(struct qed_hwfn *p_hwfn, 558fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 559fe56b9e6SYuval Mintz struct qed_sb_info *sb_info) 560fe56b9e6SYuval Mintz { 561fe56b9e6SYuval Mintz /* zero status block and ack counter */ 562fe56b9e6SYuval Mintz sb_info->sb_ack = 0; 563fe56b9e6SYuval Mintz memset(sb_info->sb_virt, 0, sizeof(*sb_info->sb_virt)); 564fe56b9e6SYuval Mintz 565fe56b9e6SYuval Mintz qed_int_cau_conf_sb(p_hwfn, p_ptt, sb_info->sb_phys, 566fe56b9e6SYuval Mintz sb_info->igu_sb_id, 0, 0); 567fe56b9e6SYuval Mintz } 568fe56b9e6SYuval Mintz 569fe56b9e6SYuval Mintz /** 570fe56b9e6SYuval Mintz * @brief qed_get_igu_sb_id - given a sw sb_id return the 571fe56b9e6SYuval Mintz * igu_sb_id 572fe56b9e6SYuval Mintz * 573fe56b9e6SYuval Mintz * @param p_hwfn 574fe56b9e6SYuval Mintz * @param sb_id 575fe56b9e6SYuval Mintz * 576fe56b9e6SYuval Mintz * @return u16 577fe56b9e6SYuval Mintz */ 578fe56b9e6SYuval Mintz static u16 qed_get_igu_sb_id(struct qed_hwfn *p_hwfn, 579fe56b9e6SYuval Mintz u16 sb_id) 580fe56b9e6SYuval Mintz { 581fe56b9e6SYuval Mintz u16 igu_sb_id; 582fe56b9e6SYuval Mintz 583fe56b9e6SYuval Mintz /* Assuming continuous set of IGU SBs dedicated for given PF */ 584fe56b9e6SYuval Mintz if (sb_id == QED_SP_SB_ID) 585fe56b9e6SYuval Mintz igu_sb_id = p_hwfn->hw_info.p_igu_info->igu_dsb_id; 586fe56b9e6SYuval Mintz else 587fe56b9e6SYuval Mintz igu_sb_id = sb_id + p_hwfn->hw_info.p_igu_info->igu_base_sb; 588fe56b9e6SYuval Mintz 589fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "SB [%s] index is 0x%04x\n", 590fe56b9e6SYuval Mintz (sb_id == QED_SP_SB_ID) ? "DSB" : "non-DSB", igu_sb_id); 591fe56b9e6SYuval Mintz 592fe56b9e6SYuval Mintz return igu_sb_id; 593fe56b9e6SYuval Mintz } 594fe56b9e6SYuval Mintz 595fe56b9e6SYuval Mintz int qed_int_sb_init(struct qed_hwfn *p_hwfn, 596fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 597fe56b9e6SYuval Mintz struct qed_sb_info *sb_info, 598fe56b9e6SYuval Mintz void *sb_virt_addr, 599fe56b9e6SYuval Mintz dma_addr_t sb_phy_addr, 600fe56b9e6SYuval Mintz u16 sb_id) 601fe56b9e6SYuval Mintz { 602fe56b9e6SYuval Mintz sb_info->sb_virt = sb_virt_addr; 603fe56b9e6SYuval Mintz sb_info->sb_phys = sb_phy_addr; 604fe56b9e6SYuval Mintz 605fe56b9e6SYuval Mintz sb_info->igu_sb_id = qed_get_igu_sb_id(p_hwfn, sb_id); 606fe56b9e6SYuval Mintz 607fe56b9e6SYuval Mintz if (sb_id != QED_SP_SB_ID) { 608fe56b9e6SYuval Mintz p_hwfn->sbs_info[sb_id] = sb_info; 609fe56b9e6SYuval Mintz p_hwfn->num_sbs++; 610fe56b9e6SYuval Mintz } 611fe56b9e6SYuval Mintz 612fe56b9e6SYuval Mintz sb_info->cdev = p_hwfn->cdev; 613fe56b9e6SYuval Mintz 614fe56b9e6SYuval Mintz /* The igu address will hold the absolute address that needs to be 615fe56b9e6SYuval Mintz * written to for a specific status block 616fe56b9e6SYuval Mintz */ 617fe56b9e6SYuval Mintz sb_info->igu_addr = (u8 __iomem *)p_hwfn->regview + 618fe56b9e6SYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 619fe56b9e6SYuval Mintz (sb_info->igu_sb_id << 3); 620fe56b9e6SYuval Mintz 621fe56b9e6SYuval Mintz sb_info->flags |= QED_SB_INFO_INIT; 622fe56b9e6SYuval Mintz 623fe56b9e6SYuval Mintz qed_int_sb_setup(p_hwfn, p_ptt, sb_info); 624fe56b9e6SYuval Mintz 625fe56b9e6SYuval Mintz return 0; 626fe56b9e6SYuval Mintz } 627fe56b9e6SYuval Mintz 628fe56b9e6SYuval Mintz int qed_int_sb_release(struct qed_hwfn *p_hwfn, 629fe56b9e6SYuval Mintz struct qed_sb_info *sb_info, 630fe56b9e6SYuval Mintz u16 sb_id) 631fe56b9e6SYuval Mintz { 632fe56b9e6SYuval Mintz if (sb_id == QED_SP_SB_ID) { 633fe56b9e6SYuval Mintz DP_ERR(p_hwfn, "Do Not free sp sb using this function"); 634fe56b9e6SYuval Mintz return -EINVAL; 635fe56b9e6SYuval Mintz } 636fe56b9e6SYuval Mintz 637fe56b9e6SYuval Mintz /* zero status block and ack counter */ 638fe56b9e6SYuval Mintz sb_info->sb_ack = 0; 639fe56b9e6SYuval Mintz memset(sb_info->sb_virt, 0, sizeof(*sb_info->sb_virt)); 640fe56b9e6SYuval Mintz 641fe56b9e6SYuval Mintz p_hwfn->sbs_info[sb_id] = NULL; 642fe56b9e6SYuval Mintz p_hwfn->num_sbs--; 643fe56b9e6SYuval Mintz 644fe56b9e6SYuval Mintz return 0; 645fe56b9e6SYuval Mintz } 646fe56b9e6SYuval Mintz 647fe56b9e6SYuval Mintz static void qed_int_sp_sb_free(struct qed_hwfn *p_hwfn) 648fe56b9e6SYuval Mintz { 649fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sb = p_hwfn->p_sp_sb; 650fe56b9e6SYuval Mintz 651fe56b9e6SYuval Mintz if (p_sb) { 652fe56b9e6SYuval Mintz if (p_sb->sb_info.sb_virt) 653fe56b9e6SYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 654fe56b9e6SYuval Mintz SB_ALIGNED_SIZE(p_hwfn), 655fe56b9e6SYuval Mintz p_sb->sb_info.sb_virt, 656fe56b9e6SYuval Mintz p_sb->sb_info.sb_phys); 657fe56b9e6SYuval Mintz kfree(p_sb); 658fe56b9e6SYuval Mintz } 659fe56b9e6SYuval Mintz } 660fe56b9e6SYuval Mintz 661fe56b9e6SYuval Mintz static int qed_int_sp_sb_alloc(struct qed_hwfn *p_hwfn, 662fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 663fe56b9e6SYuval Mintz { 664fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sb; 665fe56b9e6SYuval Mintz dma_addr_t p_phys = 0; 666fe56b9e6SYuval Mintz void *p_virt; 667fe56b9e6SYuval Mintz 668fe56b9e6SYuval Mintz /* SB struct */ 66960fffb3bSYuval Mintz p_sb = kmalloc(sizeof(*p_sb), GFP_KERNEL); 670fe56b9e6SYuval Mintz if (!p_sb) { 671fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, "Failed to allocate `struct qed_sb_info'\n"); 672fe56b9e6SYuval Mintz return -ENOMEM; 673fe56b9e6SYuval Mintz } 674fe56b9e6SYuval Mintz 675fe56b9e6SYuval Mintz /* SB ring */ 676fe56b9e6SYuval Mintz p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 677fe56b9e6SYuval Mintz SB_ALIGNED_SIZE(p_hwfn), 678fe56b9e6SYuval Mintz &p_phys, GFP_KERNEL); 679fe56b9e6SYuval Mintz if (!p_virt) { 680fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, "Failed to allocate status block\n"); 681fe56b9e6SYuval Mintz kfree(p_sb); 682fe56b9e6SYuval Mintz return -ENOMEM; 683fe56b9e6SYuval Mintz } 684fe56b9e6SYuval Mintz 685fe56b9e6SYuval Mintz /* Status Block setup */ 686fe56b9e6SYuval Mintz p_hwfn->p_sp_sb = p_sb; 687fe56b9e6SYuval Mintz qed_int_sb_init(p_hwfn, p_ptt, &p_sb->sb_info, p_virt, 688fe56b9e6SYuval Mintz p_phys, QED_SP_SB_ID); 689fe56b9e6SYuval Mintz 690fe56b9e6SYuval Mintz memset(p_sb->pi_info_arr, 0, sizeof(p_sb->pi_info_arr)); 691fe56b9e6SYuval Mintz 692fe56b9e6SYuval Mintz return 0; 693fe56b9e6SYuval Mintz } 694fe56b9e6SYuval Mintz 695fe56b9e6SYuval Mintz static void qed_int_sp_sb_setup(struct qed_hwfn *p_hwfn, 696fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 697fe56b9e6SYuval Mintz { 698fe56b9e6SYuval Mintz if (!p_hwfn) 699fe56b9e6SYuval Mintz return; 700fe56b9e6SYuval Mintz 701fe56b9e6SYuval Mintz if (p_hwfn->p_sp_sb) 702fe56b9e6SYuval Mintz qed_int_sb_setup(p_hwfn, p_ptt, &p_hwfn->p_sp_sb->sb_info); 703fe56b9e6SYuval Mintz else 704fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn->cdev, 705fe56b9e6SYuval Mintz "Failed to setup Slow path status block - NULL pointer\n"); 706cc875c2eSYuval Mintz 707cc875c2eSYuval Mintz if (p_hwfn->p_sb_attn) 708cc875c2eSYuval Mintz qed_int_sb_attn_setup(p_hwfn, p_ptt); 709cc875c2eSYuval Mintz else 710cc875c2eSYuval Mintz DP_NOTICE(p_hwfn->cdev, 711cc875c2eSYuval Mintz "Failed to setup attentions status block - NULL pointer\n"); 712fe56b9e6SYuval Mintz } 713fe56b9e6SYuval Mintz 714fe56b9e6SYuval Mintz int qed_int_register_cb(struct qed_hwfn *p_hwfn, 715fe56b9e6SYuval Mintz qed_int_comp_cb_t comp_cb, 716fe56b9e6SYuval Mintz void *cookie, 717fe56b9e6SYuval Mintz u8 *sb_idx, 718fe56b9e6SYuval Mintz __le16 **p_fw_cons) 719fe56b9e6SYuval Mintz { 720fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sp_sb = p_hwfn->p_sp_sb; 721fe56b9e6SYuval Mintz int qed_status = -ENOMEM; 722fe56b9e6SYuval Mintz u8 pi; 723fe56b9e6SYuval Mintz 724fe56b9e6SYuval Mintz /* Look for a free index */ 725fe56b9e6SYuval Mintz for (pi = 0; pi < ARRAY_SIZE(p_sp_sb->pi_info_arr); pi++) { 726fe56b9e6SYuval Mintz if (!p_sp_sb->pi_info_arr[pi].comp_cb) { 727fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].comp_cb = comp_cb; 728fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].cookie = cookie; 729fe56b9e6SYuval Mintz *sb_idx = pi; 730fe56b9e6SYuval Mintz *p_fw_cons = &p_sp_sb->sb_info.sb_virt->pi_array[pi]; 731fe56b9e6SYuval Mintz qed_status = 0; 732fe56b9e6SYuval Mintz break; 733fe56b9e6SYuval Mintz } 734fe56b9e6SYuval Mintz } 735fe56b9e6SYuval Mintz 736fe56b9e6SYuval Mintz return qed_status; 737fe56b9e6SYuval Mintz } 738fe56b9e6SYuval Mintz 739fe56b9e6SYuval Mintz int qed_int_unregister_cb(struct qed_hwfn *p_hwfn, u8 pi) 740fe56b9e6SYuval Mintz { 741fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sp_sb = p_hwfn->p_sp_sb; 742fe56b9e6SYuval Mintz int qed_status = -ENOMEM; 743fe56b9e6SYuval Mintz 744fe56b9e6SYuval Mintz if (p_sp_sb->pi_info_arr[pi].comp_cb) { 745fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].comp_cb = NULL; 746fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].cookie = NULL; 747fe56b9e6SYuval Mintz qed_status = 0; 748fe56b9e6SYuval Mintz } 749fe56b9e6SYuval Mintz 750fe56b9e6SYuval Mintz return qed_status; 751fe56b9e6SYuval Mintz } 752fe56b9e6SYuval Mintz 753fe56b9e6SYuval Mintz u16 qed_int_get_sp_sb_id(struct qed_hwfn *p_hwfn) 754fe56b9e6SYuval Mintz { 755fe56b9e6SYuval Mintz return p_hwfn->p_sp_sb->sb_info.igu_sb_id; 756fe56b9e6SYuval Mintz } 757fe56b9e6SYuval Mintz 758fe56b9e6SYuval Mintz void qed_int_igu_enable_int(struct qed_hwfn *p_hwfn, 759fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 760fe56b9e6SYuval Mintz enum qed_int_mode int_mode) 761fe56b9e6SYuval Mintz { 762cc875c2eSYuval Mintz u32 igu_pf_conf = IGU_PF_CONF_FUNC_EN | IGU_PF_CONF_ATTN_BIT_EN; 763fe56b9e6SYuval Mintz 764fe56b9e6SYuval Mintz p_hwfn->cdev->int_mode = int_mode; 765fe56b9e6SYuval Mintz switch (p_hwfn->cdev->int_mode) { 766fe56b9e6SYuval Mintz case QED_INT_MODE_INTA: 767fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_INT_LINE_EN; 768fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_SINGLE_ISR_EN; 769fe56b9e6SYuval Mintz break; 770fe56b9e6SYuval Mintz 771fe56b9e6SYuval Mintz case QED_INT_MODE_MSI: 772fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_MSI_MSIX_EN; 773fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_SINGLE_ISR_EN; 774fe56b9e6SYuval Mintz break; 775fe56b9e6SYuval Mintz 776fe56b9e6SYuval Mintz case QED_INT_MODE_MSIX: 777fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_MSI_MSIX_EN; 778fe56b9e6SYuval Mintz break; 779fe56b9e6SYuval Mintz case QED_INT_MODE_POLL: 780fe56b9e6SYuval Mintz break; 781fe56b9e6SYuval Mintz } 782fe56b9e6SYuval Mintz 783fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_PF_CONFIGURATION, igu_pf_conf); 784fe56b9e6SYuval Mintz } 785fe56b9e6SYuval Mintz 7868f16bc97SSudarsana Kalluru int qed_int_igu_enable(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, 787fe56b9e6SYuval Mintz enum qed_int_mode int_mode) 788fe56b9e6SYuval Mintz { 7898f16bc97SSudarsana Kalluru int rc, i; 790fe56b9e6SYuval Mintz 791fe56b9e6SYuval Mintz /* Mask non-link attentions */ 792fe56b9e6SYuval Mintz for (i = 0; i < 9; i++) 793fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, 794fe56b9e6SYuval Mintz MISC_REG_AEU_ENABLE1_IGU_OUT_0 + (i << 2), 0); 795fe56b9e6SYuval Mintz 796cc875c2eSYuval Mintz /* Configure AEU signal change to produce attentions for link */ 797cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_LEADING_EDGE_LATCH, 0xfff); 798cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_TRAILING_EDGE_LATCH, 0xfff); 799cc875c2eSYuval Mintz 800fe56b9e6SYuval Mintz /* Flush the writes to IGU */ 801fe56b9e6SYuval Mintz mmiowb(); 802cc875c2eSYuval Mintz 803cc875c2eSYuval Mintz /* Unmask AEU signals toward IGU */ 804cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, MISC_REG_AEU_MASK_ATTN_IGU, 0xff); 8058f16bc97SSudarsana Kalluru if ((int_mode != QED_INT_MODE_INTA) || IS_LEAD_HWFN(p_hwfn)) { 8068f16bc97SSudarsana Kalluru rc = qed_slowpath_irq_req(p_hwfn); 8078f16bc97SSudarsana Kalluru if (rc != 0) { 8088f16bc97SSudarsana Kalluru DP_NOTICE(p_hwfn, "Slowpath IRQ request failed\n"); 8098f16bc97SSudarsana Kalluru return -EINVAL; 8108f16bc97SSudarsana Kalluru } 8118f16bc97SSudarsana Kalluru p_hwfn->b_int_requested = true; 8128f16bc97SSudarsana Kalluru } 8138f16bc97SSudarsana Kalluru /* Enable interrupt Generation */ 8148f16bc97SSudarsana Kalluru qed_int_igu_enable_int(p_hwfn, p_ptt, int_mode); 8158f16bc97SSudarsana Kalluru p_hwfn->b_int_enabled = 1; 8168f16bc97SSudarsana Kalluru 8178f16bc97SSudarsana Kalluru return rc; 818fe56b9e6SYuval Mintz } 819fe56b9e6SYuval Mintz 820fe56b9e6SYuval Mintz void qed_int_igu_disable_int(struct qed_hwfn *p_hwfn, 821fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 822fe56b9e6SYuval Mintz { 823fe56b9e6SYuval Mintz p_hwfn->b_int_enabled = 0; 824fe56b9e6SYuval Mintz 825fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_PF_CONFIGURATION, 0); 826fe56b9e6SYuval Mintz } 827fe56b9e6SYuval Mintz 828fe56b9e6SYuval Mintz #define IGU_CLEANUP_SLEEP_LENGTH (1000) 829fe56b9e6SYuval Mintz void qed_int_igu_cleanup_sb(struct qed_hwfn *p_hwfn, 830fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 831fe56b9e6SYuval Mintz u32 sb_id, 832fe56b9e6SYuval Mintz bool cleanup_set, 833fe56b9e6SYuval Mintz u16 opaque_fid 834fe56b9e6SYuval Mintz ) 835fe56b9e6SYuval Mintz { 836fe56b9e6SYuval Mintz u32 pxp_addr = IGU_CMD_INT_ACK_BASE + sb_id; 837fe56b9e6SYuval Mintz u32 sleep_cnt = IGU_CLEANUP_SLEEP_LENGTH; 838fe56b9e6SYuval Mintz u32 data = 0; 839fe56b9e6SYuval Mintz u32 cmd_ctrl = 0; 840fe56b9e6SYuval Mintz u32 val = 0; 841fe56b9e6SYuval Mintz u32 sb_bit = 0; 842fe56b9e6SYuval Mintz u32 sb_bit_addr = 0; 843fe56b9e6SYuval Mintz 844fe56b9e6SYuval Mintz /* Set the data field */ 845fe56b9e6SYuval Mintz SET_FIELD(data, IGU_CLEANUP_CLEANUP_SET, cleanup_set ? 1 : 0); 846fe56b9e6SYuval Mintz SET_FIELD(data, IGU_CLEANUP_CLEANUP_TYPE, 0); 847fe56b9e6SYuval Mintz SET_FIELD(data, IGU_CLEANUP_COMMAND_TYPE, IGU_COMMAND_TYPE_SET); 848fe56b9e6SYuval Mintz 849fe56b9e6SYuval Mintz /* Set the control register */ 850fe56b9e6SYuval Mintz SET_FIELD(cmd_ctrl, IGU_CTRL_REG_PXP_ADDR, pxp_addr); 851fe56b9e6SYuval Mintz SET_FIELD(cmd_ctrl, IGU_CTRL_REG_FID, opaque_fid); 852fe56b9e6SYuval Mintz SET_FIELD(cmd_ctrl, IGU_CTRL_REG_TYPE, IGU_CTRL_CMD_TYPE_WR); 853fe56b9e6SYuval Mintz 854fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_COMMAND_REG_32LSB_DATA, data); 855fe56b9e6SYuval Mintz 856fe56b9e6SYuval Mintz barrier(); 857fe56b9e6SYuval Mintz 858fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_COMMAND_REG_CTRL, cmd_ctrl); 859fe56b9e6SYuval Mintz 860fe56b9e6SYuval Mintz /* Flush the write to IGU */ 861fe56b9e6SYuval Mintz mmiowb(); 862fe56b9e6SYuval Mintz 863fe56b9e6SYuval Mintz /* calculate where to read the status bit from */ 864fe56b9e6SYuval Mintz sb_bit = 1 << (sb_id % 32); 865fe56b9e6SYuval Mintz sb_bit_addr = sb_id / 32 * sizeof(u32); 866fe56b9e6SYuval Mintz 867fe56b9e6SYuval Mintz sb_bit_addr += IGU_REG_CLEANUP_STATUS_0; 868fe56b9e6SYuval Mintz 869fe56b9e6SYuval Mintz /* Now wait for the command to complete */ 870fe56b9e6SYuval Mintz do { 871fe56b9e6SYuval Mintz val = qed_rd(p_hwfn, p_ptt, sb_bit_addr); 872fe56b9e6SYuval Mintz 873fe56b9e6SYuval Mintz if ((val & sb_bit) == (cleanup_set ? sb_bit : 0)) 874fe56b9e6SYuval Mintz break; 875fe56b9e6SYuval Mintz 876fe56b9e6SYuval Mintz usleep_range(5000, 10000); 877fe56b9e6SYuval Mintz } while (--sleep_cnt); 878fe56b9e6SYuval Mintz 879fe56b9e6SYuval Mintz if (!sleep_cnt) 880fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, 881fe56b9e6SYuval Mintz "Timeout waiting for clear status 0x%08x [for sb %d]\n", 882fe56b9e6SYuval Mintz val, sb_id); 883fe56b9e6SYuval Mintz } 884fe56b9e6SYuval Mintz 885fe56b9e6SYuval Mintz void qed_int_igu_init_pure_rt_single(struct qed_hwfn *p_hwfn, 886fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 887fe56b9e6SYuval Mintz u32 sb_id, 888fe56b9e6SYuval Mintz u16 opaque, 889fe56b9e6SYuval Mintz bool b_set) 890fe56b9e6SYuval Mintz { 891fe56b9e6SYuval Mintz int pi; 892fe56b9e6SYuval Mintz 893fe56b9e6SYuval Mintz /* Set */ 894fe56b9e6SYuval Mintz if (b_set) 895fe56b9e6SYuval Mintz qed_int_igu_cleanup_sb(p_hwfn, p_ptt, sb_id, 1, opaque); 896fe56b9e6SYuval Mintz 897fe56b9e6SYuval Mintz /* Clear */ 898fe56b9e6SYuval Mintz qed_int_igu_cleanup_sb(p_hwfn, p_ptt, sb_id, 0, opaque); 899fe56b9e6SYuval Mintz 900fe56b9e6SYuval Mintz /* Clear the CAU for the SB */ 901fe56b9e6SYuval Mintz for (pi = 0; pi < 12; pi++) 902fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, 903fe56b9e6SYuval Mintz CAU_REG_PI_MEMORY + (sb_id * 12 + pi) * 4, 0); 904fe56b9e6SYuval Mintz } 905fe56b9e6SYuval Mintz 906fe56b9e6SYuval Mintz void qed_int_igu_init_pure_rt(struct qed_hwfn *p_hwfn, 907fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 908fe56b9e6SYuval Mintz bool b_set, 909fe56b9e6SYuval Mintz bool b_slowpath) 910fe56b9e6SYuval Mintz { 911fe56b9e6SYuval Mintz u32 igu_base_sb = p_hwfn->hw_info.p_igu_info->igu_base_sb; 912fe56b9e6SYuval Mintz u32 igu_sb_cnt = p_hwfn->hw_info.p_igu_info->igu_sb_cnt; 913fe56b9e6SYuval Mintz u32 sb_id = 0; 914fe56b9e6SYuval Mintz u32 val = 0; 915fe56b9e6SYuval Mintz 916fe56b9e6SYuval Mintz val = qed_rd(p_hwfn, p_ptt, IGU_REG_BLOCK_CONFIGURATION); 917fe56b9e6SYuval Mintz val |= IGU_REG_BLOCK_CONFIGURATION_VF_CLEANUP_EN; 918fe56b9e6SYuval Mintz val &= ~IGU_REG_BLOCK_CONFIGURATION_PXP_TPH_INTERFACE_EN; 919fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_BLOCK_CONFIGURATION, val); 920fe56b9e6SYuval Mintz 921fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 922fe56b9e6SYuval Mintz "IGU cleaning SBs [%d,...,%d]\n", 923fe56b9e6SYuval Mintz igu_base_sb, igu_base_sb + igu_sb_cnt - 1); 924fe56b9e6SYuval Mintz 925fe56b9e6SYuval Mintz for (sb_id = igu_base_sb; sb_id < igu_base_sb + igu_sb_cnt; sb_id++) 926fe56b9e6SYuval Mintz qed_int_igu_init_pure_rt_single(p_hwfn, p_ptt, sb_id, 927fe56b9e6SYuval Mintz p_hwfn->hw_info.opaque_fid, 928fe56b9e6SYuval Mintz b_set); 929fe56b9e6SYuval Mintz 930fe56b9e6SYuval Mintz if (b_slowpath) { 931fe56b9e6SYuval Mintz sb_id = p_hwfn->hw_info.p_igu_info->igu_dsb_id; 932fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 933fe56b9e6SYuval Mintz "IGU cleaning slowpath SB [%d]\n", sb_id); 934fe56b9e6SYuval Mintz qed_int_igu_init_pure_rt_single(p_hwfn, p_ptt, sb_id, 935fe56b9e6SYuval Mintz p_hwfn->hw_info.opaque_fid, 936fe56b9e6SYuval Mintz b_set); 937fe56b9e6SYuval Mintz } 938fe56b9e6SYuval Mintz } 939fe56b9e6SYuval Mintz 940fe56b9e6SYuval Mintz int qed_int_igu_read_cam(struct qed_hwfn *p_hwfn, 941fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 942fe56b9e6SYuval Mintz { 943fe56b9e6SYuval Mintz struct qed_igu_info *p_igu_info; 944fe56b9e6SYuval Mintz struct qed_igu_block *blk; 945fe56b9e6SYuval Mintz u32 val; 946fe56b9e6SYuval Mintz u16 sb_id; 947fe56b9e6SYuval Mintz u16 prev_sb_id = 0xFF; 948fe56b9e6SYuval Mintz 94960fffb3bSYuval Mintz p_hwfn->hw_info.p_igu_info = kzalloc(sizeof(*p_igu_info), GFP_KERNEL); 950fe56b9e6SYuval Mintz 951fe56b9e6SYuval Mintz if (!p_hwfn->hw_info.p_igu_info) 952fe56b9e6SYuval Mintz return -ENOMEM; 953fe56b9e6SYuval Mintz 954fe56b9e6SYuval Mintz p_igu_info = p_hwfn->hw_info.p_igu_info; 955fe56b9e6SYuval Mintz 956fe56b9e6SYuval Mintz /* Initialize base sb / sb cnt for PFs */ 957fe56b9e6SYuval Mintz p_igu_info->igu_base_sb = 0xffff; 958fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt = 0; 959fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id = 0xffff; 960fe56b9e6SYuval Mintz p_igu_info->igu_base_sb_iov = 0xffff; 961fe56b9e6SYuval Mintz 962fe56b9e6SYuval Mintz for (sb_id = 0; sb_id < QED_MAPPING_MEMORY_SIZE(p_hwfn->cdev); 963fe56b9e6SYuval Mintz sb_id++) { 964fe56b9e6SYuval Mintz blk = &p_igu_info->igu_map.igu_blocks[sb_id]; 965fe56b9e6SYuval Mintz 966fe56b9e6SYuval Mintz val = qed_rd(p_hwfn, p_ptt, 967fe56b9e6SYuval Mintz IGU_REG_MAPPING_MEMORY + sizeof(u32) * sb_id); 968fe56b9e6SYuval Mintz 969fe56b9e6SYuval Mintz /* stop scanning when hit first invalid PF entry */ 970fe56b9e6SYuval Mintz if (!GET_FIELD(val, IGU_MAPPING_LINE_VALID) && 971fe56b9e6SYuval Mintz GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID)) 972fe56b9e6SYuval Mintz break; 973fe56b9e6SYuval Mintz 974fe56b9e6SYuval Mintz blk->status = QED_IGU_STATUS_VALID; 975fe56b9e6SYuval Mintz blk->function_id = GET_FIELD(val, 976fe56b9e6SYuval Mintz IGU_MAPPING_LINE_FUNCTION_NUMBER); 977fe56b9e6SYuval Mintz blk->is_pf = GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID); 978fe56b9e6SYuval Mintz blk->vector_number = GET_FIELD(val, 979fe56b9e6SYuval Mintz IGU_MAPPING_LINE_VECTOR_NUMBER); 980fe56b9e6SYuval Mintz 981fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 982fe56b9e6SYuval Mintz "IGU_BLOCK[sb_id]:%x:func_id = %d is_pf = %d vector_num = 0x%x\n", 983fe56b9e6SYuval Mintz val, blk->function_id, blk->is_pf, 984fe56b9e6SYuval Mintz blk->vector_number); 985fe56b9e6SYuval Mintz 986fe56b9e6SYuval Mintz if (blk->is_pf) { 987fe56b9e6SYuval Mintz if (blk->function_id == p_hwfn->rel_pf_id) { 988fe56b9e6SYuval Mintz blk->status |= QED_IGU_STATUS_PF; 989fe56b9e6SYuval Mintz 990fe56b9e6SYuval Mintz if (blk->vector_number == 0) { 991fe56b9e6SYuval Mintz if (p_igu_info->igu_dsb_id == 0xffff) 992fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id = sb_id; 993fe56b9e6SYuval Mintz } else { 994fe56b9e6SYuval Mintz if (p_igu_info->igu_base_sb == 995fe56b9e6SYuval Mintz 0xffff) { 996fe56b9e6SYuval Mintz p_igu_info->igu_base_sb = sb_id; 997fe56b9e6SYuval Mintz } else if (prev_sb_id != sb_id - 1) { 998fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn->cdev, 999fe56b9e6SYuval Mintz "consecutive igu vectors for HWFN %x broken", 1000fe56b9e6SYuval Mintz p_hwfn->rel_pf_id); 1001fe56b9e6SYuval Mintz break; 1002fe56b9e6SYuval Mintz } 1003fe56b9e6SYuval Mintz prev_sb_id = sb_id; 1004fe56b9e6SYuval Mintz /* we don't count the default */ 1005fe56b9e6SYuval Mintz (p_igu_info->igu_sb_cnt)++; 1006fe56b9e6SYuval Mintz } 1007fe56b9e6SYuval Mintz } 1008fe56b9e6SYuval Mintz } 1009fe56b9e6SYuval Mintz } 1010fe56b9e6SYuval Mintz 1011fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 1012fe56b9e6SYuval Mintz "IGU igu_base_sb=0x%x igu_sb_cnt=%d igu_dsb_id=0x%x\n", 1013fe56b9e6SYuval Mintz p_igu_info->igu_base_sb, 1014fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt, 1015fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id); 1016fe56b9e6SYuval Mintz 1017fe56b9e6SYuval Mintz if (p_igu_info->igu_base_sb == 0xffff || 1018fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id == 0xffff || 1019fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt == 0) { 1020fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, 1021fe56b9e6SYuval Mintz "IGU CAM returned invalid values igu_base_sb=0x%x igu_sb_cnt=%d igu_dsb_id=0x%x\n", 1022fe56b9e6SYuval Mintz p_igu_info->igu_base_sb, 1023fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt, 1024fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id); 1025fe56b9e6SYuval Mintz return -EINVAL; 1026fe56b9e6SYuval Mintz } 1027fe56b9e6SYuval Mintz 1028fe56b9e6SYuval Mintz return 0; 1029fe56b9e6SYuval Mintz } 1030fe56b9e6SYuval Mintz 1031fe56b9e6SYuval Mintz /** 1032fe56b9e6SYuval Mintz * @brief Initialize igu runtime registers 1033fe56b9e6SYuval Mintz * 1034fe56b9e6SYuval Mintz * @param p_hwfn 1035fe56b9e6SYuval Mintz */ 1036fe56b9e6SYuval Mintz void qed_int_igu_init_rt(struct qed_hwfn *p_hwfn) 1037fe56b9e6SYuval Mintz { 1038fe56b9e6SYuval Mintz u32 igu_pf_conf = 0; 1039fe56b9e6SYuval Mintz 1040fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_FUNC_EN; 1041fe56b9e6SYuval Mintz 1042fe56b9e6SYuval Mintz STORE_RT_REG(p_hwfn, IGU_REG_PF_CONFIGURATION_RT_OFFSET, igu_pf_conf); 1043fe56b9e6SYuval Mintz } 1044fe56b9e6SYuval Mintz 1045fe56b9e6SYuval Mintz u64 qed_int_igu_read_sisr_reg(struct qed_hwfn *p_hwfn) 1046fe56b9e6SYuval Mintz { 1047fe56b9e6SYuval Mintz u64 intr_status = 0; 1048fe56b9e6SYuval Mintz u32 intr_status_lo = 0; 1049fe56b9e6SYuval Mintz u32 intr_status_hi = 0; 1050fe56b9e6SYuval Mintz u32 lsb_igu_cmd_addr = IGU_REG_SISR_MDPC_WMASK_LSB_UPPER - 1051fe56b9e6SYuval Mintz IGU_CMD_INT_ACK_BASE; 1052fe56b9e6SYuval Mintz u32 msb_igu_cmd_addr = IGU_REG_SISR_MDPC_WMASK_MSB_UPPER - 1053fe56b9e6SYuval Mintz IGU_CMD_INT_ACK_BASE; 1054fe56b9e6SYuval Mintz 1055fe56b9e6SYuval Mintz intr_status_lo = REG_RD(p_hwfn, 1056fe56b9e6SYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 1057fe56b9e6SYuval Mintz lsb_igu_cmd_addr * 8); 1058fe56b9e6SYuval Mintz intr_status_hi = REG_RD(p_hwfn, 1059fe56b9e6SYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 1060fe56b9e6SYuval Mintz msb_igu_cmd_addr * 8); 1061fe56b9e6SYuval Mintz intr_status = ((u64)intr_status_hi << 32) + (u64)intr_status_lo; 1062fe56b9e6SYuval Mintz 1063fe56b9e6SYuval Mintz return intr_status; 1064fe56b9e6SYuval Mintz } 1065fe56b9e6SYuval Mintz 1066fe56b9e6SYuval Mintz static void qed_int_sp_dpc_setup(struct qed_hwfn *p_hwfn) 1067fe56b9e6SYuval Mintz { 1068fe56b9e6SYuval Mintz tasklet_init(p_hwfn->sp_dpc, 1069fe56b9e6SYuval Mintz qed_int_sp_dpc, (unsigned long)p_hwfn); 1070fe56b9e6SYuval Mintz p_hwfn->b_sp_dpc_enabled = true; 1071fe56b9e6SYuval Mintz } 1072fe56b9e6SYuval Mintz 1073fe56b9e6SYuval Mintz static int qed_int_sp_dpc_alloc(struct qed_hwfn *p_hwfn) 1074fe56b9e6SYuval Mintz { 107560fffb3bSYuval Mintz p_hwfn->sp_dpc = kmalloc(sizeof(*p_hwfn->sp_dpc), GFP_KERNEL); 1076fe56b9e6SYuval Mintz if (!p_hwfn->sp_dpc) 1077fe56b9e6SYuval Mintz return -ENOMEM; 1078fe56b9e6SYuval Mintz 1079fe56b9e6SYuval Mintz return 0; 1080fe56b9e6SYuval Mintz } 1081fe56b9e6SYuval Mintz 1082fe56b9e6SYuval Mintz static void qed_int_sp_dpc_free(struct qed_hwfn *p_hwfn) 1083fe56b9e6SYuval Mintz { 1084fe56b9e6SYuval Mintz kfree(p_hwfn->sp_dpc); 1085fe56b9e6SYuval Mintz } 1086fe56b9e6SYuval Mintz 1087fe56b9e6SYuval Mintz int qed_int_alloc(struct qed_hwfn *p_hwfn, 1088fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 1089fe56b9e6SYuval Mintz { 1090fe56b9e6SYuval Mintz int rc = 0; 1091fe56b9e6SYuval Mintz 1092fe56b9e6SYuval Mintz rc = qed_int_sp_dpc_alloc(p_hwfn); 1093fe56b9e6SYuval Mintz if (rc) { 1094fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, "Failed to allocate sp dpc mem\n"); 1095fe56b9e6SYuval Mintz return rc; 1096fe56b9e6SYuval Mintz } 1097fe56b9e6SYuval Mintz rc = qed_int_sp_sb_alloc(p_hwfn, p_ptt); 1098fe56b9e6SYuval Mintz if (rc) { 1099fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, "Failed to allocate sp sb mem\n"); 1100fe56b9e6SYuval Mintz return rc; 1101fe56b9e6SYuval Mintz } 1102cc875c2eSYuval Mintz rc = qed_int_sb_attn_alloc(p_hwfn, p_ptt); 1103cc875c2eSYuval Mintz if (rc) { 1104cc875c2eSYuval Mintz DP_ERR(p_hwfn->cdev, "Failed to allocate sb attn mem\n"); 1105cc875c2eSYuval Mintz return rc; 1106cc875c2eSYuval Mintz } 1107fe56b9e6SYuval Mintz return rc; 1108fe56b9e6SYuval Mintz } 1109fe56b9e6SYuval Mintz 1110fe56b9e6SYuval Mintz void qed_int_free(struct qed_hwfn *p_hwfn) 1111fe56b9e6SYuval Mintz { 1112fe56b9e6SYuval Mintz qed_int_sp_sb_free(p_hwfn); 1113cc875c2eSYuval Mintz qed_int_sb_attn_free(p_hwfn); 1114fe56b9e6SYuval Mintz qed_int_sp_dpc_free(p_hwfn); 1115fe56b9e6SYuval Mintz } 1116fe56b9e6SYuval Mintz 1117fe56b9e6SYuval Mintz void qed_int_setup(struct qed_hwfn *p_hwfn, 1118fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 1119fe56b9e6SYuval Mintz { 1120fe56b9e6SYuval Mintz qed_int_sp_sb_setup(p_hwfn, p_ptt); 1121fe56b9e6SYuval Mintz qed_int_sp_dpc_setup(p_hwfn); 1122fe56b9e6SYuval Mintz } 1123fe56b9e6SYuval Mintz 1124fe56b9e6SYuval Mintz int qed_int_get_num_sbs(struct qed_hwfn *p_hwfn, 1125fe56b9e6SYuval Mintz int *p_iov_blks) 1126fe56b9e6SYuval Mintz { 1127fe56b9e6SYuval Mintz struct qed_igu_info *info = p_hwfn->hw_info.p_igu_info; 1128fe56b9e6SYuval Mintz 1129fe56b9e6SYuval Mintz if (!info) 1130fe56b9e6SYuval Mintz return 0; 1131fe56b9e6SYuval Mintz 1132fe56b9e6SYuval Mintz if (p_iov_blks) 1133fe56b9e6SYuval Mintz *p_iov_blks = info->free_blks; 1134fe56b9e6SYuval Mintz 1135fe56b9e6SYuval Mintz return info->igu_sb_cnt; 1136fe56b9e6SYuval Mintz } 11378f16bc97SSudarsana Kalluru 11388f16bc97SSudarsana Kalluru void qed_int_disable_post_isr_release(struct qed_dev *cdev) 11398f16bc97SSudarsana Kalluru { 11408f16bc97SSudarsana Kalluru int i; 11418f16bc97SSudarsana Kalluru 11428f16bc97SSudarsana Kalluru for_each_hwfn(cdev, i) 11438f16bc97SSudarsana Kalluru cdev->hwfns[i].b_int_requested = false; 11448f16bc97SSudarsana Kalluru } 1145