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_sb_attn_info *p_sb = p_hwfn->p_sb_attn; 347cc875c2eSYuval Mintz 3484ac801b7SYuval Mintz if (!p_sb) 3494ac801b7SYuval Mintz return; 3504ac801b7SYuval Mintz 351cc875c2eSYuval Mintz if (p_sb->sb_attn) 3524ac801b7SYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 353cc875c2eSYuval Mintz SB_ATTN_ALIGNED_SIZE(p_hwfn), 354cc875c2eSYuval Mintz p_sb->sb_attn, 355cc875c2eSYuval Mintz p_sb->sb_phys); 356cc875c2eSYuval Mintz kfree(p_sb); 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 { 4364ac801b7SYuval Mintz struct qed_dev *cdev = p_hwfn->cdev; 437fe56b9e6SYuval Mintz u32 cau_state; 438fe56b9e6SYuval Mintz 439fe56b9e6SYuval Mintz memset(p_sb_entry, 0, sizeof(*p_sb_entry)); 440fe56b9e6SYuval Mintz 441fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_PF_NUMBER, pf_id); 442fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_VF_NUMBER, vf_number); 443fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_VF_VALID, vf_valid); 444fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_SB_TIMESET0, 0x7F); 445fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_SB_TIMESET1, 0x7F); 446fe56b9e6SYuval Mintz 447fe56b9e6SYuval Mintz /* setting the time resultion to a fixed value ( = 1) */ 448fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_TIMER_RES0, 449fe56b9e6SYuval Mintz QED_CAU_DEF_RX_TIMER_RES); 450fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_TIMER_RES1, 451fe56b9e6SYuval Mintz QED_CAU_DEF_TX_TIMER_RES); 452fe56b9e6SYuval Mintz 453fe56b9e6SYuval Mintz cau_state = CAU_HC_DISABLE_STATE; 454fe56b9e6SYuval Mintz 4554ac801b7SYuval Mintz if (cdev->int_coalescing_mode == QED_COAL_MODE_ENABLE) { 456fe56b9e6SYuval Mintz cau_state = CAU_HC_ENABLE_STATE; 4574ac801b7SYuval Mintz if (!cdev->rx_coalesce_usecs) 4584ac801b7SYuval Mintz cdev->rx_coalesce_usecs = QED_CAU_DEF_RX_USECS; 4594ac801b7SYuval Mintz if (!cdev->tx_coalesce_usecs) 4604ac801b7SYuval Mintz cdev->tx_coalesce_usecs = QED_CAU_DEF_TX_USECS; 461fe56b9e6SYuval Mintz } 462fe56b9e6SYuval Mintz 463fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->data, CAU_SB_ENTRY_STATE0, cau_state); 464fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->data, CAU_SB_ENTRY_STATE1, cau_state); 465fe56b9e6SYuval Mintz } 466fe56b9e6SYuval Mintz 467fe56b9e6SYuval Mintz void qed_int_cau_conf_sb(struct qed_hwfn *p_hwfn, 468fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 469fe56b9e6SYuval Mintz dma_addr_t sb_phys, 470fe56b9e6SYuval Mintz u16 igu_sb_id, 471fe56b9e6SYuval Mintz u16 vf_number, 472fe56b9e6SYuval Mintz u8 vf_valid) 473fe56b9e6SYuval Mintz { 474fe56b9e6SYuval Mintz struct cau_sb_entry sb_entry; 475fe56b9e6SYuval Mintz 476fe56b9e6SYuval Mintz qed_init_cau_sb_entry(p_hwfn, &sb_entry, p_hwfn->rel_pf_id, 477fe56b9e6SYuval Mintz vf_number, vf_valid); 478fe56b9e6SYuval Mintz 479fe56b9e6SYuval Mintz if (p_hwfn->hw_init_done) { 4800a0c5d3bSYuval Mintz /* Wide-bus, initialize via DMAE */ 4810a0c5d3bSYuval Mintz u64 phys_addr = (u64)sb_phys; 482fe56b9e6SYuval Mintz 4830a0c5d3bSYuval Mintz qed_dmae_host2grc(p_hwfn, p_ptt, (u64)(uintptr_t)&phys_addr, 4840a0c5d3bSYuval Mintz CAU_REG_SB_ADDR_MEMORY + 4850a0c5d3bSYuval Mintz igu_sb_id * sizeof(u64), 2, 0); 4860a0c5d3bSYuval Mintz qed_dmae_host2grc(p_hwfn, p_ptt, (u64)(uintptr_t)&sb_entry, 4870a0c5d3bSYuval Mintz CAU_REG_SB_VAR_MEMORY + 4880a0c5d3bSYuval Mintz igu_sb_id * sizeof(u64), 2, 0); 489fe56b9e6SYuval Mintz } else { 490fe56b9e6SYuval Mintz /* Initialize Status Block Address */ 491fe56b9e6SYuval Mintz STORE_RT_REG_AGG(p_hwfn, 492fe56b9e6SYuval Mintz CAU_REG_SB_ADDR_MEMORY_RT_OFFSET + 493fe56b9e6SYuval Mintz igu_sb_id * 2, 494fe56b9e6SYuval Mintz sb_phys); 495fe56b9e6SYuval Mintz 496fe56b9e6SYuval Mintz STORE_RT_REG_AGG(p_hwfn, 497fe56b9e6SYuval Mintz CAU_REG_SB_VAR_MEMORY_RT_OFFSET + 498fe56b9e6SYuval Mintz igu_sb_id * 2, 499fe56b9e6SYuval Mintz sb_entry); 500fe56b9e6SYuval Mintz } 501fe56b9e6SYuval Mintz 502fe56b9e6SYuval Mintz /* Configure pi coalescing if set */ 503fe56b9e6SYuval Mintz if (p_hwfn->cdev->int_coalescing_mode == QED_COAL_MODE_ENABLE) { 504fe56b9e6SYuval Mintz u8 timeset = p_hwfn->cdev->rx_coalesce_usecs >> 505fe56b9e6SYuval Mintz (QED_CAU_DEF_RX_TIMER_RES + 1); 506fe56b9e6SYuval Mintz u8 num_tc = 1, i; 507fe56b9e6SYuval Mintz 508fe56b9e6SYuval Mintz qed_int_cau_conf_pi(p_hwfn, p_ptt, igu_sb_id, RX_PI, 509fe56b9e6SYuval Mintz QED_COAL_RX_STATE_MACHINE, 510fe56b9e6SYuval Mintz timeset); 511fe56b9e6SYuval Mintz 512fe56b9e6SYuval Mintz timeset = p_hwfn->cdev->tx_coalesce_usecs >> 513fe56b9e6SYuval Mintz (QED_CAU_DEF_TX_TIMER_RES + 1); 514fe56b9e6SYuval Mintz 515fe56b9e6SYuval Mintz for (i = 0; i < num_tc; i++) { 516fe56b9e6SYuval Mintz qed_int_cau_conf_pi(p_hwfn, p_ptt, 517fe56b9e6SYuval Mintz igu_sb_id, TX_PI(i), 518fe56b9e6SYuval Mintz QED_COAL_TX_STATE_MACHINE, 519fe56b9e6SYuval Mintz timeset); 520fe56b9e6SYuval Mintz } 521fe56b9e6SYuval Mintz } 522fe56b9e6SYuval Mintz } 523fe56b9e6SYuval Mintz 524fe56b9e6SYuval Mintz void qed_int_cau_conf_pi(struct qed_hwfn *p_hwfn, 525fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 526fe56b9e6SYuval Mintz u16 igu_sb_id, 527fe56b9e6SYuval Mintz u32 pi_index, 528fe56b9e6SYuval Mintz enum qed_coalescing_fsm coalescing_fsm, 529fe56b9e6SYuval Mintz u8 timeset) 530fe56b9e6SYuval Mintz { 531fe56b9e6SYuval Mintz struct cau_pi_entry pi_entry; 532fe56b9e6SYuval Mintz u32 sb_offset; 533fe56b9e6SYuval Mintz u32 pi_offset; 534fe56b9e6SYuval Mintz 535fe56b9e6SYuval Mintz sb_offset = igu_sb_id * PIS_PER_SB; 536fe56b9e6SYuval Mintz memset(&pi_entry, 0, sizeof(struct cau_pi_entry)); 537fe56b9e6SYuval Mintz 538fe56b9e6SYuval Mintz SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_PI_TIMESET, timeset); 539fe56b9e6SYuval Mintz if (coalescing_fsm == QED_COAL_RX_STATE_MACHINE) 540fe56b9e6SYuval Mintz SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_FSM_SEL, 0); 541fe56b9e6SYuval Mintz else 542fe56b9e6SYuval Mintz SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_FSM_SEL, 1); 543fe56b9e6SYuval Mintz 544fe56b9e6SYuval Mintz pi_offset = sb_offset + pi_index; 545fe56b9e6SYuval Mintz if (p_hwfn->hw_init_done) { 546fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, 547fe56b9e6SYuval Mintz CAU_REG_PI_MEMORY + pi_offset * sizeof(u32), 548fe56b9e6SYuval Mintz *((u32 *)&(pi_entry))); 549fe56b9e6SYuval Mintz } else { 550fe56b9e6SYuval Mintz STORE_RT_REG(p_hwfn, 551fe56b9e6SYuval Mintz CAU_REG_PI_MEMORY_RT_OFFSET + pi_offset, 552fe56b9e6SYuval Mintz *((u32 *)&(pi_entry))); 553fe56b9e6SYuval Mintz } 554fe56b9e6SYuval Mintz } 555fe56b9e6SYuval Mintz 556fe56b9e6SYuval Mintz void qed_int_sb_setup(struct qed_hwfn *p_hwfn, 557fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 558fe56b9e6SYuval Mintz struct qed_sb_info *sb_info) 559fe56b9e6SYuval Mintz { 560fe56b9e6SYuval Mintz /* zero status block and ack counter */ 561fe56b9e6SYuval Mintz sb_info->sb_ack = 0; 562fe56b9e6SYuval Mintz memset(sb_info->sb_virt, 0, sizeof(*sb_info->sb_virt)); 563fe56b9e6SYuval Mintz 564fe56b9e6SYuval Mintz qed_int_cau_conf_sb(p_hwfn, p_ptt, sb_info->sb_phys, 565fe56b9e6SYuval Mintz sb_info->igu_sb_id, 0, 0); 566fe56b9e6SYuval Mintz } 567fe56b9e6SYuval Mintz 568fe56b9e6SYuval Mintz /** 569fe56b9e6SYuval Mintz * @brief qed_get_igu_sb_id - given a sw sb_id return the 570fe56b9e6SYuval Mintz * igu_sb_id 571fe56b9e6SYuval Mintz * 572fe56b9e6SYuval Mintz * @param p_hwfn 573fe56b9e6SYuval Mintz * @param sb_id 574fe56b9e6SYuval Mintz * 575fe56b9e6SYuval Mintz * @return u16 576fe56b9e6SYuval Mintz */ 577fe56b9e6SYuval Mintz static u16 qed_get_igu_sb_id(struct qed_hwfn *p_hwfn, 578fe56b9e6SYuval Mintz u16 sb_id) 579fe56b9e6SYuval Mintz { 580fe56b9e6SYuval Mintz u16 igu_sb_id; 581fe56b9e6SYuval Mintz 582fe56b9e6SYuval Mintz /* Assuming continuous set of IGU SBs dedicated for given PF */ 583fe56b9e6SYuval Mintz if (sb_id == QED_SP_SB_ID) 584fe56b9e6SYuval Mintz igu_sb_id = p_hwfn->hw_info.p_igu_info->igu_dsb_id; 585fe56b9e6SYuval Mintz else 586fe56b9e6SYuval Mintz igu_sb_id = sb_id + p_hwfn->hw_info.p_igu_info->igu_base_sb; 587fe56b9e6SYuval Mintz 588fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "SB [%s] index is 0x%04x\n", 589fe56b9e6SYuval Mintz (sb_id == QED_SP_SB_ID) ? "DSB" : "non-DSB", igu_sb_id); 590fe56b9e6SYuval Mintz 591fe56b9e6SYuval Mintz return igu_sb_id; 592fe56b9e6SYuval Mintz } 593fe56b9e6SYuval Mintz 594fe56b9e6SYuval Mintz int qed_int_sb_init(struct qed_hwfn *p_hwfn, 595fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 596fe56b9e6SYuval Mintz struct qed_sb_info *sb_info, 597fe56b9e6SYuval Mintz void *sb_virt_addr, 598fe56b9e6SYuval Mintz dma_addr_t sb_phy_addr, 599fe56b9e6SYuval Mintz u16 sb_id) 600fe56b9e6SYuval Mintz { 601fe56b9e6SYuval Mintz sb_info->sb_virt = sb_virt_addr; 602fe56b9e6SYuval Mintz sb_info->sb_phys = sb_phy_addr; 603fe56b9e6SYuval Mintz 604fe56b9e6SYuval Mintz sb_info->igu_sb_id = qed_get_igu_sb_id(p_hwfn, sb_id); 605fe56b9e6SYuval Mintz 606fe56b9e6SYuval Mintz if (sb_id != QED_SP_SB_ID) { 607fe56b9e6SYuval Mintz p_hwfn->sbs_info[sb_id] = sb_info; 608fe56b9e6SYuval Mintz p_hwfn->num_sbs++; 609fe56b9e6SYuval Mintz } 610fe56b9e6SYuval Mintz 611fe56b9e6SYuval Mintz sb_info->cdev = p_hwfn->cdev; 612fe56b9e6SYuval Mintz 613fe56b9e6SYuval Mintz /* The igu address will hold the absolute address that needs to be 614fe56b9e6SYuval Mintz * written to for a specific status block 615fe56b9e6SYuval Mintz */ 616fe56b9e6SYuval Mintz sb_info->igu_addr = (u8 __iomem *)p_hwfn->regview + 617fe56b9e6SYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 618fe56b9e6SYuval Mintz (sb_info->igu_sb_id << 3); 619fe56b9e6SYuval Mintz 620fe56b9e6SYuval Mintz sb_info->flags |= QED_SB_INFO_INIT; 621fe56b9e6SYuval Mintz 622fe56b9e6SYuval Mintz qed_int_sb_setup(p_hwfn, p_ptt, sb_info); 623fe56b9e6SYuval Mintz 624fe56b9e6SYuval Mintz return 0; 625fe56b9e6SYuval Mintz } 626fe56b9e6SYuval Mintz 627fe56b9e6SYuval Mintz int qed_int_sb_release(struct qed_hwfn *p_hwfn, 628fe56b9e6SYuval Mintz struct qed_sb_info *sb_info, 629fe56b9e6SYuval Mintz u16 sb_id) 630fe56b9e6SYuval Mintz { 631fe56b9e6SYuval Mintz if (sb_id == QED_SP_SB_ID) { 632fe56b9e6SYuval Mintz DP_ERR(p_hwfn, "Do Not free sp sb using this function"); 633fe56b9e6SYuval Mintz return -EINVAL; 634fe56b9e6SYuval Mintz } 635fe56b9e6SYuval Mintz 636fe56b9e6SYuval Mintz /* zero status block and ack counter */ 637fe56b9e6SYuval Mintz sb_info->sb_ack = 0; 638fe56b9e6SYuval Mintz memset(sb_info->sb_virt, 0, sizeof(*sb_info->sb_virt)); 639fe56b9e6SYuval Mintz 6404ac801b7SYuval Mintz if (p_hwfn->sbs_info[sb_id] != NULL) { 641fe56b9e6SYuval Mintz p_hwfn->sbs_info[sb_id] = NULL; 642fe56b9e6SYuval Mintz p_hwfn->num_sbs--; 6434ac801b7SYuval Mintz } 644fe56b9e6SYuval Mintz 645fe56b9e6SYuval Mintz return 0; 646fe56b9e6SYuval Mintz } 647fe56b9e6SYuval Mintz 648fe56b9e6SYuval Mintz static void qed_int_sp_sb_free(struct qed_hwfn *p_hwfn) 649fe56b9e6SYuval Mintz { 650fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sb = p_hwfn->p_sp_sb; 651fe56b9e6SYuval Mintz 6524ac801b7SYuval Mintz if (!p_sb) 6534ac801b7SYuval Mintz return; 6544ac801b7SYuval Mintz 655fe56b9e6SYuval Mintz if (p_sb->sb_info.sb_virt) 656fe56b9e6SYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 657fe56b9e6SYuval Mintz SB_ALIGNED_SIZE(p_hwfn), 658fe56b9e6SYuval Mintz p_sb->sb_info.sb_virt, 659fe56b9e6SYuval Mintz p_sb->sb_info.sb_phys); 660fe56b9e6SYuval Mintz kfree(p_sb); 661fe56b9e6SYuval Mintz } 662fe56b9e6SYuval Mintz 663fe56b9e6SYuval Mintz static int qed_int_sp_sb_alloc(struct qed_hwfn *p_hwfn, 664fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 665fe56b9e6SYuval Mintz { 666fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sb; 667fe56b9e6SYuval Mintz dma_addr_t p_phys = 0; 668fe56b9e6SYuval Mintz void *p_virt; 669fe56b9e6SYuval Mintz 670fe56b9e6SYuval Mintz /* SB struct */ 67160fffb3bSYuval Mintz p_sb = kmalloc(sizeof(*p_sb), GFP_KERNEL); 672fe56b9e6SYuval Mintz if (!p_sb) { 673fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, "Failed to allocate `struct qed_sb_info'\n"); 674fe56b9e6SYuval Mintz return -ENOMEM; 675fe56b9e6SYuval Mintz } 676fe56b9e6SYuval Mintz 677fe56b9e6SYuval Mintz /* SB ring */ 678fe56b9e6SYuval Mintz p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 679fe56b9e6SYuval Mintz SB_ALIGNED_SIZE(p_hwfn), 680fe56b9e6SYuval Mintz &p_phys, GFP_KERNEL); 681fe56b9e6SYuval Mintz if (!p_virt) { 682fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, "Failed to allocate status block\n"); 683fe56b9e6SYuval Mintz kfree(p_sb); 684fe56b9e6SYuval Mintz return -ENOMEM; 685fe56b9e6SYuval Mintz } 686fe56b9e6SYuval Mintz 687fe56b9e6SYuval Mintz /* Status Block setup */ 688fe56b9e6SYuval Mintz p_hwfn->p_sp_sb = p_sb; 689fe56b9e6SYuval Mintz qed_int_sb_init(p_hwfn, p_ptt, &p_sb->sb_info, p_virt, 690fe56b9e6SYuval Mintz p_phys, QED_SP_SB_ID); 691fe56b9e6SYuval Mintz 692fe56b9e6SYuval Mintz memset(p_sb->pi_info_arr, 0, sizeof(p_sb->pi_info_arr)); 693fe56b9e6SYuval Mintz 694fe56b9e6SYuval Mintz return 0; 695fe56b9e6SYuval Mintz } 696fe56b9e6SYuval Mintz 697fe56b9e6SYuval Mintz static void qed_int_sp_sb_setup(struct qed_hwfn *p_hwfn, 698fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 699fe56b9e6SYuval Mintz { 700fe56b9e6SYuval Mintz if (!p_hwfn) 701fe56b9e6SYuval Mintz return; 702fe56b9e6SYuval Mintz 703fe56b9e6SYuval Mintz if (p_hwfn->p_sp_sb) 704fe56b9e6SYuval Mintz qed_int_sb_setup(p_hwfn, p_ptt, &p_hwfn->p_sp_sb->sb_info); 705fe56b9e6SYuval Mintz else 706fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn->cdev, 707fe56b9e6SYuval Mintz "Failed to setup Slow path status block - NULL pointer\n"); 708cc875c2eSYuval Mintz 709cc875c2eSYuval Mintz if (p_hwfn->p_sb_attn) 710cc875c2eSYuval Mintz qed_int_sb_attn_setup(p_hwfn, p_ptt); 711cc875c2eSYuval Mintz else 712cc875c2eSYuval Mintz DP_NOTICE(p_hwfn->cdev, 713cc875c2eSYuval Mintz "Failed to setup attentions status block - NULL pointer\n"); 714fe56b9e6SYuval Mintz } 715fe56b9e6SYuval Mintz 716fe56b9e6SYuval Mintz int qed_int_register_cb(struct qed_hwfn *p_hwfn, 717fe56b9e6SYuval Mintz qed_int_comp_cb_t comp_cb, 718fe56b9e6SYuval Mintz void *cookie, 719fe56b9e6SYuval Mintz u8 *sb_idx, 720fe56b9e6SYuval Mintz __le16 **p_fw_cons) 721fe56b9e6SYuval Mintz { 722fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sp_sb = p_hwfn->p_sp_sb; 7234ac801b7SYuval Mintz int rc = -ENOMEM; 724fe56b9e6SYuval Mintz u8 pi; 725fe56b9e6SYuval Mintz 726fe56b9e6SYuval Mintz /* Look for a free index */ 727fe56b9e6SYuval Mintz for (pi = 0; pi < ARRAY_SIZE(p_sp_sb->pi_info_arr); pi++) { 7284ac801b7SYuval Mintz if (p_sp_sb->pi_info_arr[pi].comp_cb) 7294ac801b7SYuval Mintz continue; 7304ac801b7SYuval Mintz 731fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].comp_cb = comp_cb; 732fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].cookie = cookie; 733fe56b9e6SYuval Mintz *sb_idx = pi; 734fe56b9e6SYuval Mintz *p_fw_cons = &p_sp_sb->sb_info.sb_virt->pi_array[pi]; 7354ac801b7SYuval Mintz rc = 0; 736fe56b9e6SYuval Mintz break; 737fe56b9e6SYuval Mintz } 738fe56b9e6SYuval Mintz 7394ac801b7SYuval Mintz return rc; 740fe56b9e6SYuval Mintz } 741fe56b9e6SYuval Mintz 742fe56b9e6SYuval Mintz int qed_int_unregister_cb(struct qed_hwfn *p_hwfn, u8 pi) 743fe56b9e6SYuval Mintz { 744fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sp_sb = p_hwfn->p_sp_sb; 745fe56b9e6SYuval Mintz 7464ac801b7SYuval Mintz if (p_sp_sb->pi_info_arr[pi].comp_cb == NULL) 7474ac801b7SYuval Mintz return -ENOMEM; 7484ac801b7SYuval Mintz 749fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].comp_cb = NULL; 750fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].cookie = NULL; 751fe56b9e6SYuval Mintz 7524ac801b7SYuval Mintz return 0; 753fe56b9e6SYuval Mintz } 754fe56b9e6SYuval Mintz 755fe56b9e6SYuval Mintz u16 qed_int_get_sp_sb_id(struct qed_hwfn *p_hwfn) 756fe56b9e6SYuval Mintz { 757fe56b9e6SYuval Mintz return p_hwfn->p_sp_sb->sb_info.igu_sb_id; 758fe56b9e6SYuval Mintz } 759fe56b9e6SYuval Mintz 760fe56b9e6SYuval Mintz void qed_int_igu_enable_int(struct qed_hwfn *p_hwfn, 761fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 762fe56b9e6SYuval Mintz enum qed_int_mode int_mode) 763fe56b9e6SYuval Mintz { 764cc875c2eSYuval Mintz u32 igu_pf_conf = IGU_PF_CONF_FUNC_EN | IGU_PF_CONF_ATTN_BIT_EN; 765fe56b9e6SYuval Mintz 766fe56b9e6SYuval Mintz p_hwfn->cdev->int_mode = int_mode; 767fe56b9e6SYuval Mintz switch (p_hwfn->cdev->int_mode) { 768fe56b9e6SYuval Mintz case QED_INT_MODE_INTA: 769fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_INT_LINE_EN; 770fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_SINGLE_ISR_EN; 771fe56b9e6SYuval Mintz break; 772fe56b9e6SYuval Mintz 773fe56b9e6SYuval Mintz case QED_INT_MODE_MSI: 774fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_MSI_MSIX_EN; 775fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_SINGLE_ISR_EN; 776fe56b9e6SYuval Mintz break; 777fe56b9e6SYuval Mintz 778fe56b9e6SYuval Mintz case QED_INT_MODE_MSIX: 779fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_MSI_MSIX_EN; 780fe56b9e6SYuval Mintz break; 781fe56b9e6SYuval Mintz case QED_INT_MODE_POLL: 782fe56b9e6SYuval Mintz break; 783fe56b9e6SYuval Mintz } 784fe56b9e6SYuval Mintz 785fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_PF_CONFIGURATION, igu_pf_conf); 786fe56b9e6SYuval Mintz } 787fe56b9e6SYuval Mintz 7888f16bc97SSudarsana Kalluru int qed_int_igu_enable(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, 789fe56b9e6SYuval Mintz enum qed_int_mode int_mode) 790fe56b9e6SYuval Mintz { 7918f16bc97SSudarsana Kalluru int rc, i; 792fe56b9e6SYuval Mintz 793fe56b9e6SYuval Mintz /* Mask non-link attentions */ 794fe56b9e6SYuval Mintz for (i = 0; i < 9; i++) 795fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, 796fe56b9e6SYuval Mintz MISC_REG_AEU_ENABLE1_IGU_OUT_0 + (i << 2), 0); 797fe56b9e6SYuval Mintz 798cc875c2eSYuval Mintz /* Configure AEU signal change to produce attentions for link */ 799cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_LEADING_EDGE_LATCH, 0xfff); 800cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_TRAILING_EDGE_LATCH, 0xfff); 801cc875c2eSYuval Mintz 802fe56b9e6SYuval Mintz /* Flush the writes to IGU */ 803fe56b9e6SYuval Mintz mmiowb(); 804cc875c2eSYuval Mintz 805cc875c2eSYuval Mintz /* Unmask AEU signals toward IGU */ 806cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, MISC_REG_AEU_MASK_ATTN_IGU, 0xff); 8078f16bc97SSudarsana Kalluru if ((int_mode != QED_INT_MODE_INTA) || IS_LEAD_HWFN(p_hwfn)) { 8088f16bc97SSudarsana Kalluru rc = qed_slowpath_irq_req(p_hwfn); 8098f16bc97SSudarsana Kalluru if (rc != 0) { 8108f16bc97SSudarsana Kalluru DP_NOTICE(p_hwfn, "Slowpath IRQ request failed\n"); 8118f16bc97SSudarsana Kalluru return -EINVAL; 8128f16bc97SSudarsana Kalluru } 8138f16bc97SSudarsana Kalluru p_hwfn->b_int_requested = true; 8148f16bc97SSudarsana Kalluru } 8158f16bc97SSudarsana Kalluru /* Enable interrupt Generation */ 8168f16bc97SSudarsana Kalluru qed_int_igu_enable_int(p_hwfn, p_ptt, int_mode); 8178f16bc97SSudarsana Kalluru p_hwfn->b_int_enabled = 1; 8188f16bc97SSudarsana Kalluru 8198f16bc97SSudarsana Kalluru return rc; 820fe56b9e6SYuval Mintz } 821fe56b9e6SYuval Mintz 822fe56b9e6SYuval Mintz void qed_int_igu_disable_int(struct qed_hwfn *p_hwfn, 823fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 824fe56b9e6SYuval Mintz { 825fe56b9e6SYuval Mintz p_hwfn->b_int_enabled = 0; 826fe56b9e6SYuval Mintz 827fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_PF_CONFIGURATION, 0); 828fe56b9e6SYuval Mintz } 829fe56b9e6SYuval Mintz 830fe56b9e6SYuval Mintz #define IGU_CLEANUP_SLEEP_LENGTH (1000) 831fe56b9e6SYuval Mintz void qed_int_igu_cleanup_sb(struct qed_hwfn *p_hwfn, 832fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 833fe56b9e6SYuval Mintz u32 sb_id, 834fe56b9e6SYuval Mintz bool cleanup_set, 835fe56b9e6SYuval Mintz u16 opaque_fid 836fe56b9e6SYuval Mintz ) 837fe56b9e6SYuval Mintz { 838fe56b9e6SYuval Mintz u32 pxp_addr = IGU_CMD_INT_ACK_BASE + sb_id; 839fe56b9e6SYuval Mintz u32 sleep_cnt = IGU_CLEANUP_SLEEP_LENGTH; 840fe56b9e6SYuval Mintz u32 data = 0; 841fe56b9e6SYuval Mintz u32 cmd_ctrl = 0; 842fe56b9e6SYuval Mintz u32 val = 0; 843fe56b9e6SYuval Mintz u32 sb_bit = 0; 844fe56b9e6SYuval Mintz u32 sb_bit_addr = 0; 845fe56b9e6SYuval Mintz 846fe56b9e6SYuval Mintz /* Set the data field */ 847fe56b9e6SYuval Mintz SET_FIELD(data, IGU_CLEANUP_CLEANUP_SET, cleanup_set ? 1 : 0); 848fe56b9e6SYuval Mintz SET_FIELD(data, IGU_CLEANUP_CLEANUP_TYPE, 0); 849fe56b9e6SYuval Mintz SET_FIELD(data, IGU_CLEANUP_COMMAND_TYPE, IGU_COMMAND_TYPE_SET); 850fe56b9e6SYuval Mintz 851fe56b9e6SYuval Mintz /* Set the control register */ 852fe56b9e6SYuval Mintz SET_FIELD(cmd_ctrl, IGU_CTRL_REG_PXP_ADDR, pxp_addr); 853fe56b9e6SYuval Mintz SET_FIELD(cmd_ctrl, IGU_CTRL_REG_FID, opaque_fid); 854fe56b9e6SYuval Mintz SET_FIELD(cmd_ctrl, IGU_CTRL_REG_TYPE, IGU_CTRL_CMD_TYPE_WR); 855fe56b9e6SYuval Mintz 856fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_COMMAND_REG_32LSB_DATA, data); 857fe56b9e6SYuval Mintz 858fe56b9e6SYuval Mintz barrier(); 859fe56b9e6SYuval Mintz 860fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_COMMAND_REG_CTRL, cmd_ctrl); 861fe56b9e6SYuval Mintz 862fe56b9e6SYuval Mintz /* Flush the write to IGU */ 863fe56b9e6SYuval Mintz mmiowb(); 864fe56b9e6SYuval Mintz 865fe56b9e6SYuval Mintz /* calculate where to read the status bit from */ 866fe56b9e6SYuval Mintz sb_bit = 1 << (sb_id % 32); 867fe56b9e6SYuval Mintz sb_bit_addr = sb_id / 32 * sizeof(u32); 868fe56b9e6SYuval Mintz 869fe56b9e6SYuval Mintz sb_bit_addr += IGU_REG_CLEANUP_STATUS_0; 870fe56b9e6SYuval Mintz 871fe56b9e6SYuval Mintz /* Now wait for the command to complete */ 872fe56b9e6SYuval Mintz do { 873fe56b9e6SYuval Mintz val = qed_rd(p_hwfn, p_ptt, sb_bit_addr); 874fe56b9e6SYuval Mintz 875fe56b9e6SYuval Mintz if ((val & sb_bit) == (cleanup_set ? sb_bit : 0)) 876fe56b9e6SYuval Mintz break; 877fe56b9e6SYuval Mintz 878fe56b9e6SYuval Mintz usleep_range(5000, 10000); 879fe56b9e6SYuval Mintz } while (--sleep_cnt); 880fe56b9e6SYuval Mintz 881fe56b9e6SYuval Mintz if (!sleep_cnt) 882fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, 883fe56b9e6SYuval Mintz "Timeout waiting for clear status 0x%08x [for sb %d]\n", 884fe56b9e6SYuval Mintz val, sb_id); 885fe56b9e6SYuval Mintz } 886fe56b9e6SYuval Mintz 887fe56b9e6SYuval Mintz void qed_int_igu_init_pure_rt_single(struct qed_hwfn *p_hwfn, 888fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 889fe56b9e6SYuval Mintz u32 sb_id, 890fe56b9e6SYuval Mintz u16 opaque, 891fe56b9e6SYuval Mintz bool b_set) 892fe56b9e6SYuval Mintz { 893fe56b9e6SYuval Mintz int pi; 894fe56b9e6SYuval Mintz 895fe56b9e6SYuval Mintz /* Set */ 896fe56b9e6SYuval Mintz if (b_set) 897fe56b9e6SYuval Mintz qed_int_igu_cleanup_sb(p_hwfn, p_ptt, sb_id, 1, opaque); 898fe56b9e6SYuval Mintz 899fe56b9e6SYuval Mintz /* Clear */ 900fe56b9e6SYuval Mintz qed_int_igu_cleanup_sb(p_hwfn, p_ptt, sb_id, 0, opaque); 901fe56b9e6SYuval Mintz 902fe56b9e6SYuval Mintz /* Clear the CAU for the SB */ 903fe56b9e6SYuval Mintz for (pi = 0; pi < 12; pi++) 904fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, 905fe56b9e6SYuval Mintz CAU_REG_PI_MEMORY + (sb_id * 12 + pi) * 4, 0); 906fe56b9e6SYuval Mintz } 907fe56b9e6SYuval Mintz 908fe56b9e6SYuval Mintz void qed_int_igu_init_pure_rt(struct qed_hwfn *p_hwfn, 909fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 910fe56b9e6SYuval Mintz bool b_set, 911fe56b9e6SYuval Mintz bool b_slowpath) 912fe56b9e6SYuval Mintz { 913fe56b9e6SYuval Mintz u32 igu_base_sb = p_hwfn->hw_info.p_igu_info->igu_base_sb; 914fe56b9e6SYuval Mintz u32 igu_sb_cnt = p_hwfn->hw_info.p_igu_info->igu_sb_cnt; 915fe56b9e6SYuval Mintz u32 sb_id = 0; 916fe56b9e6SYuval Mintz u32 val = 0; 917fe56b9e6SYuval Mintz 918fe56b9e6SYuval Mintz val = qed_rd(p_hwfn, p_ptt, IGU_REG_BLOCK_CONFIGURATION); 919fe56b9e6SYuval Mintz val |= IGU_REG_BLOCK_CONFIGURATION_VF_CLEANUP_EN; 920fe56b9e6SYuval Mintz val &= ~IGU_REG_BLOCK_CONFIGURATION_PXP_TPH_INTERFACE_EN; 921fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_BLOCK_CONFIGURATION, val); 922fe56b9e6SYuval Mintz 923fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 924fe56b9e6SYuval Mintz "IGU cleaning SBs [%d,...,%d]\n", 925fe56b9e6SYuval Mintz igu_base_sb, igu_base_sb + igu_sb_cnt - 1); 926fe56b9e6SYuval Mintz 927fe56b9e6SYuval Mintz for (sb_id = igu_base_sb; sb_id < igu_base_sb + igu_sb_cnt; sb_id++) 928fe56b9e6SYuval Mintz qed_int_igu_init_pure_rt_single(p_hwfn, p_ptt, sb_id, 929fe56b9e6SYuval Mintz p_hwfn->hw_info.opaque_fid, 930fe56b9e6SYuval Mintz b_set); 931fe56b9e6SYuval Mintz 932fe56b9e6SYuval Mintz if (b_slowpath) { 933fe56b9e6SYuval Mintz sb_id = p_hwfn->hw_info.p_igu_info->igu_dsb_id; 934fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 935fe56b9e6SYuval Mintz "IGU cleaning slowpath SB [%d]\n", sb_id); 936fe56b9e6SYuval Mintz qed_int_igu_init_pure_rt_single(p_hwfn, p_ptt, sb_id, 937fe56b9e6SYuval Mintz p_hwfn->hw_info.opaque_fid, 938fe56b9e6SYuval Mintz b_set); 939fe56b9e6SYuval Mintz } 940fe56b9e6SYuval Mintz } 941fe56b9e6SYuval Mintz 9424ac801b7SYuval Mintz static u32 qed_int_igu_read_cam_block(struct qed_hwfn *p_hwfn, 9434ac801b7SYuval Mintz struct qed_ptt *p_ptt, 9444ac801b7SYuval Mintz u16 sb_id) 9454ac801b7SYuval Mintz { 9464ac801b7SYuval Mintz u32 val = qed_rd(p_hwfn, p_ptt, 9474ac801b7SYuval Mintz IGU_REG_MAPPING_MEMORY + 9484ac801b7SYuval Mintz sizeof(u32) * sb_id); 9494ac801b7SYuval Mintz struct qed_igu_block *p_block; 9504ac801b7SYuval Mintz 9514ac801b7SYuval Mintz p_block = &p_hwfn->hw_info.p_igu_info->igu_map.igu_blocks[sb_id]; 9524ac801b7SYuval Mintz 9534ac801b7SYuval Mintz /* stop scanning when hit first invalid PF entry */ 9544ac801b7SYuval Mintz if (!GET_FIELD(val, IGU_MAPPING_LINE_VALID) && 9554ac801b7SYuval Mintz GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID)) 9564ac801b7SYuval Mintz goto out; 9574ac801b7SYuval Mintz 9584ac801b7SYuval Mintz /* Fill the block information */ 9594ac801b7SYuval Mintz p_block->status = QED_IGU_STATUS_VALID; 9604ac801b7SYuval Mintz p_block->function_id = GET_FIELD(val, 9614ac801b7SYuval Mintz IGU_MAPPING_LINE_FUNCTION_NUMBER); 9624ac801b7SYuval Mintz p_block->is_pf = GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID); 9634ac801b7SYuval Mintz p_block->vector_number = GET_FIELD(val, 9644ac801b7SYuval Mintz IGU_MAPPING_LINE_VECTOR_NUMBER); 9654ac801b7SYuval Mintz 9664ac801b7SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 9674ac801b7SYuval Mintz "IGU_BLOCK: [SB 0x%04x, Value in CAM 0x%08x] func_id = %d is_pf = %d vector_num = 0x%x\n", 9684ac801b7SYuval Mintz sb_id, val, p_block->function_id, 9694ac801b7SYuval Mintz p_block->is_pf, p_block->vector_number); 9704ac801b7SYuval Mintz 9714ac801b7SYuval Mintz out: 9724ac801b7SYuval Mintz return val; 9734ac801b7SYuval Mintz } 9744ac801b7SYuval Mintz 975fe56b9e6SYuval Mintz int qed_int_igu_read_cam(struct qed_hwfn *p_hwfn, 976fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 977fe56b9e6SYuval Mintz { 978fe56b9e6SYuval Mintz struct qed_igu_info *p_igu_info; 979fe56b9e6SYuval Mintz struct qed_igu_block *blk; 980fe56b9e6SYuval Mintz u32 val; 981fe56b9e6SYuval Mintz u16 sb_id; 982fe56b9e6SYuval Mintz u16 prev_sb_id = 0xFF; 983fe56b9e6SYuval Mintz 98460fffb3bSYuval Mintz p_hwfn->hw_info.p_igu_info = kzalloc(sizeof(*p_igu_info), GFP_KERNEL); 985fe56b9e6SYuval Mintz 986fe56b9e6SYuval Mintz if (!p_hwfn->hw_info.p_igu_info) 987fe56b9e6SYuval Mintz return -ENOMEM; 988fe56b9e6SYuval Mintz 989fe56b9e6SYuval Mintz p_igu_info = p_hwfn->hw_info.p_igu_info; 990fe56b9e6SYuval Mintz 991fe56b9e6SYuval Mintz /* Initialize base sb / sb cnt for PFs */ 992fe56b9e6SYuval Mintz p_igu_info->igu_base_sb = 0xffff; 993fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt = 0; 994fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id = 0xffff; 995fe56b9e6SYuval Mintz p_igu_info->igu_base_sb_iov = 0xffff; 996fe56b9e6SYuval Mintz 997fe56b9e6SYuval Mintz for (sb_id = 0; sb_id < QED_MAPPING_MEMORY_SIZE(p_hwfn->cdev); 998fe56b9e6SYuval Mintz sb_id++) { 999fe56b9e6SYuval Mintz blk = &p_igu_info->igu_map.igu_blocks[sb_id]; 1000fe56b9e6SYuval Mintz 10014ac801b7SYuval Mintz val = qed_int_igu_read_cam_block(p_hwfn, p_ptt, sb_id); 1002fe56b9e6SYuval Mintz 1003fe56b9e6SYuval Mintz /* stop scanning when hit first invalid PF entry */ 1004fe56b9e6SYuval Mintz if (!GET_FIELD(val, IGU_MAPPING_LINE_VALID) && 1005fe56b9e6SYuval Mintz GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID)) 1006fe56b9e6SYuval Mintz break; 1007fe56b9e6SYuval Mintz 1008fe56b9e6SYuval Mintz if (blk->is_pf) { 1009fe56b9e6SYuval Mintz if (blk->function_id == p_hwfn->rel_pf_id) { 1010fe56b9e6SYuval Mintz blk->status |= QED_IGU_STATUS_PF; 1011fe56b9e6SYuval Mintz 1012fe56b9e6SYuval Mintz if (blk->vector_number == 0) { 1013fe56b9e6SYuval Mintz if (p_igu_info->igu_dsb_id == 0xffff) 1014fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id = sb_id; 1015fe56b9e6SYuval Mintz } else { 1016fe56b9e6SYuval Mintz if (p_igu_info->igu_base_sb == 1017fe56b9e6SYuval Mintz 0xffff) { 1018fe56b9e6SYuval Mintz p_igu_info->igu_base_sb = sb_id; 1019fe56b9e6SYuval Mintz } else if (prev_sb_id != sb_id - 1) { 1020fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn->cdev, 1021fe56b9e6SYuval Mintz "consecutive igu vectors for HWFN %x broken", 1022fe56b9e6SYuval Mintz p_hwfn->rel_pf_id); 1023fe56b9e6SYuval Mintz break; 1024fe56b9e6SYuval Mintz } 1025fe56b9e6SYuval Mintz prev_sb_id = sb_id; 1026fe56b9e6SYuval Mintz /* we don't count the default */ 1027fe56b9e6SYuval Mintz (p_igu_info->igu_sb_cnt)++; 1028fe56b9e6SYuval Mintz } 1029fe56b9e6SYuval Mintz } 1030fe56b9e6SYuval Mintz } 1031fe56b9e6SYuval Mintz } 1032fe56b9e6SYuval Mintz 1033fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 1034fe56b9e6SYuval Mintz "IGU igu_base_sb=0x%x igu_sb_cnt=%d igu_dsb_id=0x%x\n", 1035fe56b9e6SYuval Mintz p_igu_info->igu_base_sb, 1036fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt, 1037fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id); 1038fe56b9e6SYuval Mintz 1039fe56b9e6SYuval Mintz if (p_igu_info->igu_base_sb == 0xffff || 1040fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id == 0xffff || 1041fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt == 0) { 1042fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, 1043fe56b9e6SYuval Mintz "IGU CAM returned invalid values igu_base_sb=0x%x igu_sb_cnt=%d igu_dsb_id=0x%x\n", 1044fe56b9e6SYuval Mintz p_igu_info->igu_base_sb, 1045fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt, 1046fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id); 1047fe56b9e6SYuval Mintz return -EINVAL; 1048fe56b9e6SYuval Mintz } 1049fe56b9e6SYuval Mintz 1050fe56b9e6SYuval Mintz return 0; 1051fe56b9e6SYuval Mintz } 1052fe56b9e6SYuval Mintz 1053fe56b9e6SYuval Mintz /** 1054fe56b9e6SYuval Mintz * @brief Initialize igu runtime registers 1055fe56b9e6SYuval Mintz * 1056fe56b9e6SYuval Mintz * @param p_hwfn 1057fe56b9e6SYuval Mintz */ 1058fe56b9e6SYuval Mintz void qed_int_igu_init_rt(struct qed_hwfn *p_hwfn) 1059fe56b9e6SYuval Mintz { 1060fe56b9e6SYuval Mintz u32 igu_pf_conf = 0; 1061fe56b9e6SYuval Mintz 1062fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_FUNC_EN; 1063fe56b9e6SYuval Mintz 1064fe56b9e6SYuval Mintz STORE_RT_REG(p_hwfn, IGU_REG_PF_CONFIGURATION_RT_OFFSET, igu_pf_conf); 1065fe56b9e6SYuval Mintz } 1066fe56b9e6SYuval Mintz 1067fe56b9e6SYuval Mintz u64 qed_int_igu_read_sisr_reg(struct qed_hwfn *p_hwfn) 1068fe56b9e6SYuval Mintz { 1069fe56b9e6SYuval Mintz u64 intr_status = 0; 1070fe56b9e6SYuval Mintz u32 intr_status_lo = 0; 1071fe56b9e6SYuval Mintz u32 intr_status_hi = 0; 1072fe56b9e6SYuval Mintz u32 lsb_igu_cmd_addr = IGU_REG_SISR_MDPC_WMASK_LSB_UPPER - 1073fe56b9e6SYuval Mintz IGU_CMD_INT_ACK_BASE; 1074fe56b9e6SYuval Mintz u32 msb_igu_cmd_addr = IGU_REG_SISR_MDPC_WMASK_MSB_UPPER - 1075fe56b9e6SYuval Mintz IGU_CMD_INT_ACK_BASE; 1076fe56b9e6SYuval Mintz 1077fe56b9e6SYuval Mintz intr_status_lo = REG_RD(p_hwfn, 1078fe56b9e6SYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 1079fe56b9e6SYuval Mintz lsb_igu_cmd_addr * 8); 1080fe56b9e6SYuval Mintz intr_status_hi = REG_RD(p_hwfn, 1081fe56b9e6SYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 1082fe56b9e6SYuval Mintz msb_igu_cmd_addr * 8); 1083fe56b9e6SYuval Mintz intr_status = ((u64)intr_status_hi << 32) + (u64)intr_status_lo; 1084fe56b9e6SYuval Mintz 1085fe56b9e6SYuval Mintz return intr_status; 1086fe56b9e6SYuval Mintz } 1087fe56b9e6SYuval Mintz 1088fe56b9e6SYuval Mintz static void qed_int_sp_dpc_setup(struct qed_hwfn *p_hwfn) 1089fe56b9e6SYuval Mintz { 1090fe56b9e6SYuval Mintz tasklet_init(p_hwfn->sp_dpc, 1091fe56b9e6SYuval Mintz qed_int_sp_dpc, (unsigned long)p_hwfn); 1092fe56b9e6SYuval Mintz p_hwfn->b_sp_dpc_enabled = true; 1093fe56b9e6SYuval Mintz } 1094fe56b9e6SYuval Mintz 1095fe56b9e6SYuval Mintz static int qed_int_sp_dpc_alloc(struct qed_hwfn *p_hwfn) 1096fe56b9e6SYuval Mintz { 109760fffb3bSYuval Mintz p_hwfn->sp_dpc = kmalloc(sizeof(*p_hwfn->sp_dpc), GFP_KERNEL); 1098fe56b9e6SYuval Mintz if (!p_hwfn->sp_dpc) 1099fe56b9e6SYuval Mintz return -ENOMEM; 1100fe56b9e6SYuval Mintz 1101fe56b9e6SYuval Mintz return 0; 1102fe56b9e6SYuval Mintz } 1103fe56b9e6SYuval Mintz 1104fe56b9e6SYuval Mintz static void qed_int_sp_dpc_free(struct qed_hwfn *p_hwfn) 1105fe56b9e6SYuval Mintz { 1106fe56b9e6SYuval Mintz kfree(p_hwfn->sp_dpc); 1107fe56b9e6SYuval Mintz } 1108fe56b9e6SYuval Mintz 1109fe56b9e6SYuval Mintz int qed_int_alloc(struct qed_hwfn *p_hwfn, 1110fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 1111fe56b9e6SYuval Mintz { 1112fe56b9e6SYuval Mintz int rc = 0; 1113fe56b9e6SYuval Mintz 1114fe56b9e6SYuval Mintz rc = qed_int_sp_dpc_alloc(p_hwfn); 1115fe56b9e6SYuval Mintz if (rc) { 1116fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, "Failed to allocate sp dpc mem\n"); 1117fe56b9e6SYuval Mintz return rc; 1118fe56b9e6SYuval Mintz } 1119fe56b9e6SYuval Mintz rc = qed_int_sp_sb_alloc(p_hwfn, p_ptt); 1120fe56b9e6SYuval Mintz if (rc) { 1121fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, "Failed to allocate sp sb mem\n"); 1122fe56b9e6SYuval Mintz return rc; 1123fe56b9e6SYuval Mintz } 1124cc875c2eSYuval Mintz rc = qed_int_sb_attn_alloc(p_hwfn, p_ptt); 1125cc875c2eSYuval Mintz if (rc) { 1126cc875c2eSYuval Mintz DP_ERR(p_hwfn->cdev, "Failed to allocate sb attn mem\n"); 1127cc875c2eSYuval Mintz return rc; 1128cc875c2eSYuval Mintz } 1129fe56b9e6SYuval Mintz return rc; 1130fe56b9e6SYuval Mintz } 1131fe56b9e6SYuval Mintz 1132fe56b9e6SYuval Mintz void qed_int_free(struct qed_hwfn *p_hwfn) 1133fe56b9e6SYuval Mintz { 1134fe56b9e6SYuval Mintz qed_int_sp_sb_free(p_hwfn); 1135cc875c2eSYuval Mintz qed_int_sb_attn_free(p_hwfn); 1136fe56b9e6SYuval Mintz qed_int_sp_dpc_free(p_hwfn); 1137fe56b9e6SYuval Mintz } 1138fe56b9e6SYuval Mintz 1139fe56b9e6SYuval Mintz void qed_int_setup(struct qed_hwfn *p_hwfn, 1140fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 1141fe56b9e6SYuval Mintz { 1142fe56b9e6SYuval Mintz qed_int_sp_sb_setup(p_hwfn, p_ptt); 1143fe56b9e6SYuval Mintz qed_int_sp_dpc_setup(p_hwfn); 1144fe56b9e6SYuval Mintz } 1145fe56b9e6SYuval Mintz 11464ac801b7SYuval Mintz void qed_int_get_num_sbs(struct qed_hwfn *p_hwfn, 11474ac801b7SYuval Mintz struct qed_sb_cnt_info *p_sb_cnt_info) 1148fe56b9e6SYuval Mintz { 1149fe56b9e6SYuval Mintz struct qed_igu_info *info = p_hwfn->hw_info.p_igu_info; 1150fe56b9e6SYuval Mintz 11514ac801b7SYuval Mintz if (!info || !p_sb_cnt_info) 11524ac801b7SYuval Mintz return; 1153fe56b9e6SYuval Mintz 11544ac801b7SYuval Mintz p_sb_cnt_info->sb_cnt = info->igu_sb_cnt; 11554ac801b7SYuval Mintz p_sb_cnt_info->sb_iov_cnt = info->igu_sb_cnt_iov; 11564ac801b7SYuval Mintz p_sb_cnt_info->sb_free_blk = info->free_blks; 1157fe56b9e6SYuval Mintz } 11588f16bc97SSudarsana Kalluru 11598f16bc97SSudarsana Kalluru void qed_int_disable_post_isr_release(struct qed_dev *cdev) 11608f16bc97SSudarsana Kalluru { 11618f16bc97SSudarsana Kalluru int i; 11628f16bc97SSudarsana Kalluru 11638f16bc97SSudarsana Kalluru for_each_hwfn(cdev, i) 11648f16bc97SSudarsana Kalluru cdev->hwfns[i].b_int_requested = false; 11658f16bc97SSudarsana Kalluru } 1166