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) { 255fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, "DPC called - no hwfn!\n"); 256fe56b9e6SYuval Mintz return; 257fe56b9e6SYuval Mintz } 258fe56b9e6SYuval Mintz 259fe56b9e6SYuval Mintz if (!p_hwfn->p_sp_sb) { 260fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, "DPC called - no p_sp_sb\n"); 261fe56b9e6SYuval Mintz return; 262fe56b9e6SYuval Mintz } 263fe56b9e6SYuval Mintz 264fe56b9e6SYuval Mintz sb_info = &p_hwfn->p_sp_sb->sb_info; 265fe56b9e6SYuval Mintz arr_size = ARRAY_SIZE(p_hwfn->p_sp_sb->pi_info_arr); 266fe56b9e6SYuval Mintz if (!sb_info) { 267fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, 268fe56b9e6SYuval Mintz "Status block is NULL - cannot ack interrupts\n"); 269fe56b9e6SYuval Mintz return; 270fe56b9e6SYuval Mintz } 271fe56b9e6SYuval Mintz 272cc875c2eSYuval Mintz if (!p_hwfn->p_sb_attn) { 273cc875c2eSYuval Mintz DP_ERR(p_hwfn->cdev, "DPC called - no p_sb_attn"); 274cc875c2eSYuval Mintz return; 275cc875c2eSYuval Mintz } 276cc875c2eSYuval Mintz sb_attn = p_hwfn->p_sb_attn; 277cc875c2eSYuval Mintz 278fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "DPC Called! (hwfn %p %d)\n", 279fe56b9e6SYuval Mintz p_hwfn, p_hwfn->my_id); 280fe56b9e6SYuval Mintz 281fe56b9e6SYuval Mintz /* Disable ack for def status block. Required both for msix + 282fe56b9e6SYuval Mintz * inta in non-mask mode, in inta does no harm. 283fe56b9e6SYuval Mintz */ 284fe56b9e6SYuval Mintz qed_sb_ack(sb_info, IGU_INT_DISABLE, 0); 285fe56b9e6SYuval Mintz 286fe56b9e6SYuval Mintz /* Gather Interrupts/Attentions information */ 287fe56b9e6SYuval Mintz if (!sb_info->sb_virt) { 288fe56b9e6SYuval Mintz DP_ERR( 289fe56b9e6SYuval Mintz p_hwfn->cdev, 290fe56b9e6SYuval Mintz "Interrupt Status block is NULL - cannot check for new interrupts!\n"); 291fe56b9e6SYuval Mintz } else { 292fe56b9e6SYuval Mintz u32 tmp_index = sb_info->sb_ack; 293fe56b9e6SYuval Mintz 294fe56b9e6SYuval Mintz rc = qed_sb_update_sb_idx(sb_info); 295fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn->cdev, NETIF_MSG_INTR, 296fe56b9e6SYuval Mintz "Interrupt indices: 0x%08x --> 0x%08x\n", 297fe56b9e6SYuval Mintz tmp_index, sb_info->sb_ack); 298fe56b9e6SYuval Mintz } 299fe56b9e6SYuval Mintz 300cc875c2eSYuval Mintz if (!sb_attn || !sb_attn->sb_attn) { 301cc875c2eSYuval Mintz DP_ERR( 302cc875c2eSYuval Mintz p_hwfn->cdev, 303cc875c2eSYuval Mintz "Attentions Status block is NULL - cannot check for new attentions!\n"); 304cc875c2eSYuval Mintz } else { 305cc875c2eSYuval Mintz u16 tmp_index = sb_attn->index; 306cc875c2eSYuval Mintz 307cc875c2eSYuval Mintz rc |= qed_attn_update_idx(p_hwfn, sb_attn); 308cc875c2eSYuval Mintz DP_VERBOSE(p_hwfn->cdev, NETIF_MSG_INTR, 309cc875c2eSYuval Mintz "Attention indices: 0x%08x --> 0x%08x\n", 310cc875c2eSYuval Mintz tmp_index, sb_attn->index); 311cc875c2eSYuval Mintz } 312cc875c2eSYuval Mintz 313fe56b9e6SYuval Mintz /* Check if we expect interrupts at this time. if not just ack them */ 314fe56b9e6SYuval Mintz if (!(rc & QED_SB_EVENT_MASK)) { 315fe56b9e6SYuval Mintz qed_sb_ack(sb_info, IGU_INT_ENABLE, 1); 316fe56b9e6SYuval Mintz return; 317fe56b9e6SYuval Mintz } 318fe56b9e6SYuval Mintz 319fe56b9e6SYuval Mintz /* Check the validity of the DPC ptt. If not ack interrupts and fail */ 320fe56b9e6SYuval Mintz if (!p_hwfn->p_dpc_ptt) { 321fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn->cdev, "Failed to allocate PTT\n"); 322fe56b9e6SYuval Mintz qed_sb_ack(sb_info, IGU_INT_ENABLE, 1); 323fe56b9e6SYuval Mintz return; 324fe56b9e6SYuval Mintz } 325fe56b9e6SYuval Mintz 326cc875c2eSYuval Mintz if (rc & QED_SB_ATT_IDX) 327cc875c2eSYuval Mintz qed_int_attentions(p_hwfn); 328cc875c2eSYuval Mintz 329fe56b9e6SYuval Mintz if (rc & QED_SB_IDX) { 330fe56b9e6SYuval Mintz int pi; 331fe56b9e6SYuval Mintz 332fe56b9e6SYuval Mintz /* Look for a free index */ 333fe56b9e6SYuval Mintz for (pi = 0; pi < arr_size; pi++) { 334fe56b9e6SYuval Mintz pi_info = &p_hwfn->p_sp_sb->pi_info_arr[pi]; 335fe56b9e6SYuval Mintz if (pi_info->comp_cb) 336fe56b9e6SYuval Mintz pi_info->comp_cb(p_hwfn, pi_info->cookie); 337fe56b9e6SYuval Mintz } 338fe56b9e6SYuval Mintz } 339fe56b9e6SYuval Mintz 340cc875c2eSYuval Mintz if (sb_attn && (rc & QED_SB_ATT_IDX)) 341cc875c2eSYuval Mintz /* This should be done before the interrupts are enabled, 342cc875c2eSYuval Mintz * since otherwise a new attention will be generated. 343cc875c2eSYuval Mintz */ 344cc875c2eSYuval Mintz qed_sb_ack_attn(p_hwfn, sb_info->igu_addr, sb_attn->index); 345cc875c2eSYuval Mintz 346fe56b9e6SYuval Mintz qed_sb_ack(sb_info, IGU_INT_ENABLE, 1); 347fe56b9e6SYuval Mintz } 348fe56b9e6SYuval Mintz 349cc875c2eSYuval Mintz static void qed_int_sb_attn_free(struct qed_hwfn *p_hwfn) 350cc875c2eSYuval Mintz { 351cc875c2eSYuval Mintz struct qed_dev *cdev = p_hwfn->cdev; 352cc875c2eSYuval Mintz struct qed_sb_attn_info *p_sb = p_hwfn->p_sb_attn; 353cc875c2eSYuval Mintz 354cc875c2eSYuval Mintz if (p_sb) { 355cc875c2eSYuval Mintz if (p_sb->sb_attn) 356cc875c2eSYuval Mintz dma_free_coherent(&cdev->pdev->dev, 357cc875c2eSYuval Mintz SB_ATTN_ALIGNED_SIZE(p_hwfn), 358cc875c2eSYuval Mintz p_sb->sb_attn, 359cc875c2eSYuval Mintz p_sb->sb_phys); 360cc875c2eSYuval Mintz kfree(p_sb); 361cc875c2eSYuval Mintz } 362cc875c2eSYuval Mintz } 363cc875c2eSYuval Mintz 364cc875c2eSYuval Mintz static void qed_int_sb_attn_setup(struct qed_hwfn *p_hwfn, 365cc875c2eSYuval Mintz struct qed_ptt *p_ptt) 366cc875c2eSYuval Mintz { 367cc875c2eSYuval Mintz struct qed_sb_attn_info *sb_info = p_hwfn->p_sb_attn; 368cc875c2eSYuval Mintz 369cc875c2eSYuval Mintz memset(sb_info->sb_attn, 0, sizeof(*sb_info->sb_attn)); 370cc875c2eSYuval Mintz 371cc875c2eSYuval Mintz sb_info->index = 0; 372cc875c2eSYuval Mintz sb_info->known_attn = 0; 373cc875c2eSYuval Mintz 374cc875c2eSYuval Mintz /* Configure Attention Status Block in IGU */ 375cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_ATTN_MSG_ADDR_L, 376cc875c2eSYuval Mintz lower_32_bits(p_hwfn->p_sb_attn->sb_phys)); 377cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_ATTN_MSG_ADDR_H, 378cc875c2eSYuval Mintz upper_32_bits(p_hwfn->p_sb_attn->sb_phys)); 379cc875c2eSYuval Mintz } 380cc875c2eSYuval Mintz 381cc875c2eSYuval Mintz static void qed_int_sb_attn_init(struct qed_hwfn *p_hwfn, 382cc875c2eSYuval Mintz struct qed_ptt *p_ptt, 383cc875c2eSYuval Mintz void *sb_virt_addr, 384cc875c2eSYuval Mintz dma_addr_t sb_phy_addr) 385cc875c2eSYuval Mintz { 386cc875c2eSYuval Mintz struct qed_sb_attn_info *sb_info = p_hwfn->p_sb_attn; 387cc875c2eSYuval Mintz 388cc875c2eSYuval Mintz sb_info->sb_attn = sb_virt_addr; 389cc875c2eSYuval Mintz sb_info->sb_phys = sb_phy_addr; 390cc875c2eSYuval Mintz 391cc875c2eSYuval Mintz /* Set the address of cleanup for the mcp attention */ 392cc875c2eSYuval Mintz sb_info->mfw_attn_addr = (p_hwfn->rel_pf_id << 3) + 393cc875c2eSYuval Mintz MISC_REG_AEU_GENERAL_ATTN_0; 394cc875c2eSYuval Mintz 395cc875c2eSYuval Mintz qed_int_sb_attn_setup(p_hwfn, p_ptt); 396cc875c2eSYuval Mintz } 397cc875c2eSYuval Mintz 398cc875c2eSYuval Mintz static int qed_int_sb_attn_alloc(struct qed_hwfn *p_hwfn, 399cc875c2eSYuval Mintz struct qed_ptt *p_ptt) 400cc875c2eSYuval Mintz { 401cc875c2eSYuval Mintz struct qed_dev *cdev = p_hwfn->cdev; 402cc875c2eSYuval Mintz struct qed_sb_attn_info *p_sb; 403cc875c2eSYuval Mintz void *p_virt; 404cc875c2eSYuval Mintz dma_addr_t p_phys = 0; 405cc875c2eSYuval Mintz 406cc875c2eSYuval Mintz /* SB struct */ 407cc875c2eSYuval Mintz p_sb = kmalloc(sizeof(*p_sb), GFP_ATOMIC); 408cc875c2eSYuval Mintz if (!p_sb) { 409cc875c2eSYuval Mintz DP_NOTICE(cdev, "Failed to allocate `struct qed_sb_attn_info'\n"); 410cc875c2eSYuval Mintz return -ENOMEM; 411cc875c2eSYuval Mintz } 412cc875c2eSYuval Mintz 413cc875c2eSYuval Mintz /* SB ring */ 414cc875c2eSYuval Mintz p_virt = dma_alloc_coherent(&cdev->pdev->dev, 415cc875c2eSYuval Mintz SB_ATTN_ALIGNED_SIZE(p_hwfn), 416cc875c2eSYuval Mintz &p_phys, GFP_KERNEL); 417cc875c2eSYuval Mintz 418cc875c2eSYuval Mintz if (!p_virt) { 419cc875c2eSYuval Mintz DP_NOTICE(cdev, "Failed to allocate status block (attentions)\n"); 420cc875c2eSYuval Mintz kfree(p_sb); 421cc875c2eSYuval Mintz return -ENOMEM; 422cc875c2eSYuval Mintz } 423cc875c2eSYuval Mintz 424cc875c2eSYuval Mintz /* Attention setup */ 425cc875c2eSYuval Mintz p_hwfn->p_sb_attn = p_sb; 426cc875c2eSYuval Mintz qed_int_sb_attn_init(p_hwfn, p_ptt, p_virt, p_phys); 427cc875c2eSYuval Mintz 428cc875c2eSYuval Mintz return 0; 429cc875c2eSYuval Mintz } 430cc875c2eSYuval Mintz 431fe56b9e6SYuval Mintz /* coalescing timeout = timeset << (timer_res + 1) */ 432fe56b9e6SYuval Mintz #define QED_CAU_DEF_RX_USECS 24 433fe56b9e6SYuval Mintz #define QED_CAU_DEF_TX_USECS 48 434fe56b9e6SYuval Mintz 435fe56b9e6SYuval Mintz void qed_init_cau_sb_entry(struct qed_hwfn *p_hwfn, 436fe56b9e6SYuval Mintz struct cau_sb_entry *p_sb_entry, 437fe56b9e6SYuval Mintz u8 pf_id, 438fe56b9e6SYuval Mintz u16 vf_number, 439fe56b9e6SYuval Mintz u8 vf_valid) 440fe56b9e6SYuval Mintz { 441fe56b9e6SYuval Mintz u32 cau_state; 442fe56b9e6SYuval Mintz 443fe56b9e6SYuval Mintz memset(p_sb_entry, 0, sizeof(*p_sb_entry)); 444fe56b9e6SYuval Mintz 445fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_PF_NUMBER, pf_id); 446fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_VF_NUMBER, vf_number); 447fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_VF_VALID, vf_valid); 448fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_SB_TIMESET0, 0x7F); 449fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_SB_TIMESET1, 0x7F); 450fe56b9e6SYuval Mintz 451fe56b9e6SYuval Mintz /* setting the time resultion to a fixed value ( = 1) */ 452fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_TIMER_RES0, 453fe56b9e6SYuval Mintz QED_CAU_DEF_RX_TIMER_RES); 454fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_TIMER_RES1, 455fe56b9e6SYuval Mintz QED_CAU_DEF_TX_TIMER_RES); 456fe56b9e6SYuval Mintz 457fe56b9e6SYuval Mintz cau_state = CAU_HC_DISABLE_STATE; 458fe56b9e6SYuval Mintz 459fe56b9e6SYuval Mintz if (p_hwfn->cdev->int_coalescing_mode == QED_COAL_MODE_ENABLE) { 460fe56b9e6SYuval Mintz cau_state = CAU_HC_ENABLE_STATE; 461fe56b9e6SYuval Mintz if (!p_hwfn->cdev->rx_coalesce_usecs) 462fe56b9e6SYuval Mintz p_hwfn->cdev->rx_coalesce_usecs = 463fe56b9e6SYuval Mintz QED_CAU_DEF_RX_USECS; 464fe56b9e6SYuval Mintz if (!p_hwfn->cdev->tx_coalesce_usecs) 465fe56b9e6SYuval Mintz p_hwfn->cdev->tx_coalesce_usecs = 466fe56b9e6SYuval Mintz QED_CAU_DEF_TX_USECS; 467fe56b9e6SYuval Mintz } 468fe56b9e6SYuval Mintz 469fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->data, CAU_SB_ENTRY_STATE0, cau_state); 470fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->data, CAU_SB_ENTRY_STATE1, cau_state); 471fe56b9e6SYuval Mintz } 472fe56b9e6SYuval Mintz 473fe56b9e6SYuval Mintz void qed_int_cau_conf_sb(struct qed_hwfn *p_hwfn, 474fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 475fe56b9e6SYuval Mintz dma_addr_t sb_phys, 476fe56b9e6SYuval Mintz u16 igu_sb_id, 477fe56b9e6SYuval Mintz u16 vf_number, 478fe56b9e6SYuval Mintz u8 vf_valid) 479fe56b9e6SYuval Mintz { 480fe56b9e6SYuval Mintz struct cau_sb_entry sb_entry; 481fe56b9e6SYuval Mintz u32 val; 482fe56b9e6SYuval Mintz 483fe56b9e6SYuval Mintz qed_init_cau_sb_entry(p_hwfn, &sb_entry, p_hwfn->rel_pf_id, 484fe56b9e6SYuval Mintz vf_number, vf_valid); 485fe56b9e6SYuval Mintz 486fe56b9e6SYuval Mintz if (p_hwfn->hw_init_done) { 487fe56b9e6SYuval Mintz val = CAU_REG_SB_ADDR_MEMORY + igu_sb_id * sizeof(u64); 488fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, val, lower_32_bits(sb_phys)); 489fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, val + sizeof(u32), 490fe56b9e6SYuval Mintz upper_32_bits(sb_phys)); 491fe56b9e6SYuval Mintz 492fe56b9e6SYuval Mintz val = CAU_REG_SB_VAR_MEMORY + igu_sb_id * sizeof(u64); 493fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, val, sb_entry.data); 494fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, val + sizeof(u32), sb_entry.params); 495fe56b9e6SYuval Mintz } else { 496fe56b9e6SYuval Mintz /* Initialize Status Block Address */ 497fe56b9e6SYuval Mintz STORE_RT_REG_AGG(p_hwfn, 498fe56b9e6SYuval Mintz CAU_REG_SB_ADDR_MEMORY_RT_OFFSET + 499fe56b9e6SYuval Mintz igu_sb_id * 2, 500fe56b9e6SYuval Mintz sb_phys); 501fe56b9e6SYuval Mintz 502fe56b9e6SYuval Mintz STORE_RT_REG_AGG(p_hwfn, 503fe56b9e6SYuval Mintz CAU_REG_SB_VAR_MEMORY_RT_OFFSET + 504fe56b9e6SYuval Mintz igu_sb_id * 2, 505fe56b9e6SYuval Mintz sb_entry); 506fe56b9e6SYuval Mintz } 507fe56b9e6SYuval Mintz 508fe56b9e6SYuval Mintz /* Configure pi coalescing if set */ 509fe56b9e6SYuval Mintz if (p_hwfn->cdev->int_coalescing_mode == QED_COAL_MODE_ENABLE) { 510fe56b9e6SYuval Mintz u8 timeset = p_hwfn->cdev->rx_coalesce_usecs >> 511fe56b9e6SYuval Mintz (QED_CAU_DEF_RX_TIMER_RES + 1); 512fe56b9e6SYuval Mintz u8 num_tc = 1, i; 513fe56b9e6SYuval Mintz 514fe56b9e6SYuval Mintz qed_int_cau_conf_pi(p_hwfn, p_ptt, igu_sb_id, RX_PI, 515fe56b9e6SYuval Mintz QED_COAL_RX_STATE_MACHINE, 516fe56b9e6SYuval Mintz timeset); 517fe56b9e6SYuval Mintz 518fe56b9e6SYuval Mintz timeset = p_hwfn->cdev->tx_coalesce_usecs >> 519fe56b9e6SYuval Mintz (QED_CAU_DEF_TX_TIMER_RES + 1); 520fe56b9e6SYuval Mintz 521fe56b9e6SYuval Mintz for (i = 0; i < num_tc; i++) { 522fe56b9e6SYuval Mintz qed_int_cau_conf_pi(p_hwfn, p_ptt, 523fe56b9e6SYuval Mintz igu_sb_id, TX_PI(i), 524fe56b9e6SYuval Mintz QED_COAL_TX_STATE_MACHINE, 525fe56b9e6SYuval Mintz timeset); 526fe56b9e6SYuval Mintz } 527fe56b9e6SYuval Mintz } 528fe56b9e6SYuval Mintz } 529fe56b9e6SYuval Mintz 530fe56b9e6SYuval Mintz void qed_int_cau_conf_pi(struct qed_hwfn *p_hwfn, 531fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 532fe56b9e6SYuval Mintz u16 igu_sb_id, 533fe56b9e6SYuval Mintz u32 pi_index, 534fe56b9e6SYuval Mintz enum qed_coalescing_fsm coalescing_fsm, 535fe56b9e6SYuval Mintz u8 timeset) 536fe56b9e6SYuval Mintz { 537fe56b9e6SYuval Mintz struct cau_pi_entry pi_entry; 538fe56b9e6SYuval Mintz u32 sb_offset; 539fe56b9e6SYuval Mintz u32 pi_offset; 540fe56b9e6SYuval Mintz 541fe56b9e6SYuval Mintz sb_offset = igu_sb_id * PIS_PER_SB; 542fe56b9e6SYuval Mintz memset(&pi_entry, 0, sizeof(struct cau_pi_entry)); 543fe56b9e6SYuval Mintz 544fe56b9e6SYuval Mintz SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_PI_TIMESET, timeset); 545fe56b9e6SYuval Mintz if (coalescing_fsm == QED_COAL_RX_STATE_MACHINE) 546fe56b9e6SYuval Mintz SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_FSM_SEL, 0); 547fe56b9e6SYuval Mintz else 548fe56b9e6SYuval Mintz SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_FSM_SEL, 1); 549fe56b9e6SYuval Mintz 550fe56b9e6SYuval Mintz pi_offset = sb_offset + pi_index; 551fe56b9e6SYuval Mintz if (p_hwfn->hw_init_done) { 552fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, 553fe56b9e6SYuval Mintz CAU_REG_PI_MEMORY + pi_offset * sizeof(u32), 554fe56b9e6SYuval Mintz *((u32 *)&(pi_entry))); 555fe56b9e6SYuval Mintz } else { 556fe56b9e6SYuval Mintz STORE_RT_REG(p_hwfn, 557fe56b9e6SYuval Mintz CAU_REG_PI_MEMORY_RT_OFFSET + pi_offset, 558fe56b9e6SYuval Mintz *((u32 *)&(pi_entry))); 559fe56b9e6SYuval Mintz } 560fe56b9e6SYuval Mintz } 561fe56b9e6SYuval Mintz 562fe56b9e6SYuval Mintz void qed_int_sb_setup(struct qed_hwfn *p_hwfn, 563fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 564fe56b9e6SYuval Mintz struct qed_sb_info *sb_info) 565fe56b9e6SYuval Mintz { 566fe56b9e6SYuval Mintz /* zero status block and ack counter */ 567fe56b9e6SYuval Mintz sb_info->sb_ack = 0; 568fe56b9e6SYuval Mintz memset(sb_info->sb_virt, 0, sizeof(*sb_info->sb_virt)); 569fe56b9e6SYuval Mintz 570fe56b9e6SYuval Mintz qed_int_cau_conf_sb(p_hwfn, p_ptt, sb_info->sb_phys, 571fe56b9e6SYuval Mintz sb_info->igu_sb_id, 0, 0); 572fe56b9e6SYuval Mintz } 573fe56b9e6SYuval Mintz 574fe56b9e6SYuval Mintz /** 575fe56b9e6SYuval Mintz * @brief qed_get_igu_sb_id - given a sw sb_id return the 576fe56b9e6SYuval Mintz * igu_sb_id 577fe56b9e6SYuval Mintz * 578fe56b9e6SYuval Mintz * @param p_hwfn 579fe56b9e6SYuval Mintz * @param sb_id 580fe56b9e6SYuval Mintz * 581fe56b9e6SYuval Mintz * @return u16 582fe56b9e6SYuval Mintz */ 583fe56b9e6SYuval Mintz static u16 qed_get_igu_sb_id(struct qed_hwfn *p_hwfn, 584fe56b9e6SYuval Mintz u16 sb_id) 585fe56b9e6SYuval Mintz { 586fe56b9e6SYuval Mintz u16 igu_sb_id; 587fe56b9e6SYuval Mintz 588fe56b9e6SYuval Mintz /* Assuming continuous set of IGU SBs dedicated for given PF */ 589fe56b9e6SYuval Mintz if (sb_id == QED_SP_SB_ID) 590fe56b9e6SYuval Mintz igu_sb_id = p_hwfn->hw_info.p_igu_info->igu_dsb_id; 591fe56b9e6SYuval Mintz else 592fe56b9e6SYuval Mintz igu_sb_id = sb_id + p_hwfn->hw_info.p_igu_info->igu_base_sb; 593fe56b9e6SYuval Mintz 594fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "SB [%s] index is 0x%04x\n", 595fe56b9e6SYuval Mintz (sb_id == QED_SP_SB_ID) ? "DSB" : "non-DSB", igu_sb_id); 596fe56b9e6SYuval Mintz 597fe56b9e6SYuval Mintz return igu_sb_id; 598fe56b9e6SYuval Mintz } 599fe56b9e6SYuval Mintz 600fe56b9e6SYuval Mintz int qed_int_sb_init(struct qed_hwfn *p_hwfn, 601fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 602fe56b9e6SYuval Mintz struct qed_sb_info *sb_info, 603fe56b9e6SYuval Mintz void *sb_virt_addr, 604fe56b9e6SYuval Mintz dma_addr_t sb_phy_addr, 605fe56b9e6SYuval Mintz u16 sb_id) 606fe56b9e6SYuval Mintz { 607fe56b9e6SYuval Mintz sb_info->sb_virt = sb_virt_addr; 608fe56b9e6SYuval Mintz sb_info->sb_phys = sb_phy_addr; 609fe56b9e6SYuval Mintz 610fe56b9e6SYuval Mintz sb_info->igu_sb_id = qed_get_igu_sb_id(p_hwfn, sb_id); 611fe56b9e6SYuval Mintz 612fe56b9e6SYuval Mintz if (sb_id != QED_SP_SB_ID) { 613fe56b9e6SYuval Mintz p_hwfn->sbs_info[sb_id] = sb_info; 614fe56b9e6SYuval Mintz p_hwfn->num_sbs++; 615fe56b9e6SYuval Mintz } 616fe56b9e6SYuval Mintz 617fe56b9e6SYuval Mintz sb_info->cdev = p_hwfn->cdev; 618fe56b9e6SYuval Mintz 619fe56b9e6SYuval Mintz /* The igu address will hold the absolute address that needs to be 620fe56b9e6SYuval Mintz * written to for a specific status block 621fe56b9e6SYuval Mintz */ 622fe56b9e6SYuval Mintz sb_info->igu_addr = (u8 __iomem *)p_hwfn->regview + 623fe56b9e6SYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 624fe56b9e6SYuval Mintz (sb_info->igu_sb_id << 3); 625fe56b9e6SYuval Mintz 626fe56b9e6SYuval Mintz sb_info->flags |= QED_SB_INFO_INIT; 627fe56b9e6SYuval Mintz 628fe56b9e6SYuval Mintz qed_int_sb_setup(p_hwfn, p_ptt, sb_info); 629fe56b9e6SYuval Mintz 630fe56b9e6SYuval Mintz return 0; 631fe56b9e6SYuval Mintz } 632fe56b9e6SYuval Mintz 633fe56b9e6SYuval Mintz int qed_int_sb_release(struct qed_hwfn *p_hwfn, 634fe56b9e6SYuval Mintz struct qed_sb_info *sb_info, 635fe56b9e6SYuval Mintz u16 sb_id) 636fe56b9e6SYuval Mintz { 637fe56b9e6SYuval Mintz if (sb_id == QED_SP_SB_ID) { 638fe56b9e6SYuval Mintz DP_ERR(p_hwfn, "Do Not free sp sb using this function"); 639fe56b9e6SYuval Mintz return -EINVAL; 640fe56b9e6SYuval Mintz } 641fe56b9e6SYuval Mintz 642fe56b9e6SYuval Mintz /* zero status block and ack counter */ 643fe56b9e6SYuval Mintz sb_info->sb_ack = 0; 644fe56b9e6SYuval Mintz memset(sb_info->sb_virt, 0, sizeof(*sb_info->sb_virt)); 645fe56b9e6SYuval Mintz 646fe56b9e6SYuval Mintz p_hwfn->sbs_info[sb_id] = NULL; 647fe56b9e6SYuval Mintz p_hwfn->num_sbs--; 648fe56b9e6SYuval Mintz 649fe56b9e6SYuval Mintz return 0; 650fe56b9e6SYuval Mintz } 651fe56b9e6SYuval Mintz 652fe56b9e6SYuval Mintz static void qed_int_sp_sb_free(struct qed_hwfn *p_hwfn) 653fe56b9e6SYuval Mintz { 654fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sb = p_hwfn->p_sp_sb; 655fe56b9e6SYuval Mintz 656fe56b9e6SYuval Mintz if (p_sb) { 657fe56b9e6SYuval Mintz if (p_sb->sb_info.sb_virt) 658fe56b9e6SYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 659fe56b9e6SYuval Mintz SB_ALIGNED_SIZE(p_hwfn), 660fe56b9e6SYuval Mintz p_sb->sb_info.sb_virt, 661fe56b9e6SYuval Mintz p_sb->sb_info.sb_phys); 662fe56b9e6SYuval Mintz kfree(p_sb); 663fe56b9e6SYuval Mintz } 664fe56b9e6SYuval Mintz } 665fe56b9e6SYuval Mintz 666fe56b9e6SYuval Mintz static int qed_int_sp_sb_alloc(struct qed_hwfn *p_hwfn, 667fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 668fe56b9e6SYuval Mintz { 669fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sb; 670fe56b9e6SYuval Mintz dma_addr_t p_phys = 0; 671fe56b9e6SYuval Mintz void *p_virt; 672fe56b9e6SYuval Mintz 673fe56b9e6SYuval Mintz /* SB struct */ 674fe56b9e6SYuval Mintz p_sb = kmalloc(sizeof(*p_sb), GFP_ATOMIC); 675fe56b9e6SYuval Mintz if (!p_sb) { 676fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, "Failed to allocate `struct qed_sb_info'\n"); 677fe56b9e6SYuval Mintz return -ENOMEM; 678fe56b9e6SYuval Mintz } 679fe56b9e6SYuval Mintz 680fe56b9e6SYuval Mintz /* SB ring */ 681fe56b9e6SYuval Mintz p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 682fe56b9e6SYuval Mintz SB_ALIGNED_SIZE(p_hwfn), 683fe56b9e6SYuval Mintz &p_phys, GFP_KERNEL); 684fe56b9e6SYuval Mintz if (!p_virt) { 685fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, "Failed to allocate status block\n"); 686fe56b9e6SYuval Mintz kfree(p_sb); 687fe56b9e6SYuval Mintz return -ENOMEM; 688fe56b9e6SYuval Mintz } 689fe56b9e6SYuval Mintz 690fe56b9e6SYuval Mintz /* Status Block setup */ 691fe56b9e6SYuval Mintz p_hwfn->p_sp_sb = p_sb; 692fe56b9e6SYuval Mintz qed_int_sb_init(p_hwfn, p_ptt, &p_sb->sb_info, p_virt, 693fe56b9e6SYuval Mintz p_phys, QED_SP_SB_ID); 694fe56b9e6SYuval Mintz 695fe56b9e6SYuval Mintz memset(p_sb->pi_info_arr, 0, sizeof(p_sb->pi_info_arr)); 696fe56b9e6SYuval Mintz 697fe56b9e6SYuval Mintz return 0; 698fe56b9e6SYuval Mintz } 699fe56b9e6SYuval Mintz 700fe56b9e6SYuval Mintz static void qed_int_sp_sb_setup(struct qed_hwfn *p_hwfn, 701fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 702fe56b9e6SYuval Mintz { 703fe56b9e6SYuval Mintz if (!p_hwfn) 704fe56b9e6SYuval Mintz return; 705fe56b9e6SYuval Mintz 706fe56b9e6SYuval Mintz if (p_hwfn->p_sp_sb) 707fe56b9e6SYuval Mintz qed_int_sb_setup(p_hwfn, p_ptt, &p_hwfn->p_sp_sb->sb_info); 708fe56b9e6SYuval Mintz else 709fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn->cdev, 710fe56b9e6SYuval Mintz "Failed to setup Slow path status block - NULL pointer\n"); 711cc875c2eSYuval Mintz 712cc875c2eSYuval Mintz if (p_hwfn->p_sb_attn) 713cc875c2eSYuval Mintz qed_int_sb_attn_setup(p_hwfn, p_ptt); 714cc875c2eSYuval Mintz else 715cc875c2eSYuval Mintz DP_NOTICE(p_hwfn->cdev, 716cc875c2eSYuval Mintz "Failed to setup attentions status block - NULL pointer\n"); 717fe56b9e6SYuval Mintz } 718fe56b9e6SYuval Mintz 719fe56b9e6SYuval Mintz int qed_int_register_cb(struct qed_hwfn *p_hwfn, 720fe56b9e6SYuval Mintz qed_int_comp_cb_t comp_cb, 721fe56b9e6SYuval Mintz void *cookie, 722fe56b9e6SYuval Mintz u8 *sb_idx, 723fe56b9e6SYuval Mintz __le16 **p_fw_cons) 724fe56b9e6SYuval Mintz { 725fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sp_sb = p_hwfn->p_sp_sb; 726fe56b9e6SYuval Mintz int qed_status = -ENOMEM; 727fe56b9e6SYuval Mintz u8 pi; 728fe56b9e6SYuval Mintz 729fe56b9e6SYuval Mintz /* Look for a free index */ 730fe56b9e6SYuval Mintz for (pi = 0; pi < ARRAY_SIZE(p_sp_sb->pi_info_arr); pi++) { 731fe56b9e6SYuval Mintz if (!p_sp_sb->pi_info_arr[pi].comp_cb) { 732fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].comp_cb = comp_cb; 733fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].cookie = cookie; 734fe56b9e6SYuval Mintz *sb_idx = pi; 735fe56b9e6SYuval Mintz *p_fw_cons = &p_sp_sb->sb_info.sb_virt->pi_array[pi]; 736fe56b9e6SYuval Mintz qed_status = 0; 737fe56b9e6SYuval Mintz break; 738fe56b9e6SYuval Mintz } 739fe56b9e6SYuval Mintz } 740fe56b9e6SYuval Mintz 741fe56b9e6SYuval Mintz return qed_status; 742fe56b9e6SYuval Mintz } 743fe56b9e6SYuval Mintz 744fe56b9e6SYuval Mintz int qed_int_unregister_cb(struct qed_hwfn *p_hwfn, u8 pi) 745fe56b9e6SYuval Mintz { 746fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sp_sb = p_hwfn->p_sp_sb; 747fe56b9e6SYuval Mintz int qed_status = -ENOMEM; 748fe56b9e6SYuval Mintz 749fe56b9e6SYuval Mintz if (p_sp_sb->pi_info_arr[pi].comp_cb) { 750fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].comp_cb = NULL; 751fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].cookie = NULL; 752fe56b9e6SYuval Mintz qed_status = 0; 753fe56b9e6SYuval Mintz } 754fe56b9e6SYuval Mintz 755fe56b9e6SYuval Mintz return qed_status; 756fe56b9e6SYuval Mintz } 757fe56b9e6SYuval Mintz 758fe56b9e6SYuval Mintz u16 qed_int_get_sp_sb_id(struct qed_hwfn *p_hwfn) 759fe56b9e6SYuval Mintz { 760fe56b9e6SYuval Mintz return p_hwfn->p_sp_sb->sb_info.igu_sb_id; 761fe56b9e6SYuval Mintz } 762fe56b9e6SYuval Mintz 763fe56b9e6SYuval Mintz void qed_int_igu_enable_int(struct qed_hwfn *p_hwfn, 764fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 765fe56b9e6SYuval Mintz enum qed_int_mode int_mode) 766fe56b9e6SYuval Mintz { 767cc875c2eSYuval Mintz u32 igu_pf_conf = IGU_PF_CONF_FUNC_EN | IGU_PF_CONF_ATTN_BIT_EN; 768fe56b9e6SYuval Mintz 769fe56b9e6SYuval Mintz p_hwfn->cdev->int_mode = int_mode; 770fe56b9e6SYuval Mintz switch (p_hwfn->cdev->int_mode) { 771fe56b9e6SYuval Mintz case QED_INT_MODE_INTA: 772fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_INT_LINE_EN; 773fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_SINGLE_ISR_EN; 774fe56b9e6SYuval Mintz break; 775fe56b9e6SYuval Mintz 776fe56b9e6SYuval Mintz case QED_INT_MODE_MSI: 777fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_MSI_MSIX_EN; 778fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_SINGLE_ISR_EN; 779fe56b9e6SYuval Mintz break; 780fe56b9e6SYuval Mintz 781fe56b9e6SYuval Mintz case QED_INT_MODE_MSIX: 782fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_MSI_MSIX_EN; 783fe56b9e6SYuval Mintz break; 784fe56b9e6SYuval Mintz case QED_INT_MODE_POLL: 785fe56b9e6SYuval Mintz break; 786fe56b9e6SYuval Mintz } 787fe56b9e6SYuval Mintz 788fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_PF_CONFIGURATION, igu_pf_conf); 789fe56b9e6SYuval Mintz } 790fe56b9e6SYuval Mintz 791fe56b9e6SYuval Mintz void qed_int_igu_enable(struct qed_hwfn *p_hwfn, 792fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 793fe56b9e6SYuval Mintz enum qed_int_mode int_mode) 794fe56b9e6SYuval Mintz { 795fe56b9e6SYuval Mintz int i; 796fe56b9e6SYuval Mintz 797fe56b9e6SYuval Mintz p_hwfn->b_int_enabled = 1; 798fe56b9e6SYuval Mintz 799fe56b9e6SYuval Mintz /* Mask non-link attentions */ 800fe56b9e6SYuval Mintz for (i = 0; i < 9; i++) 801fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, 802fe56b9e6SYuval Mintz MISC_REG_AEU_ENABLE1_IGU_OUT_0 + (i << 2), 0); 803fe56b9e6SYuval Mintz 804fe56b9e6SYuval Mintz /* Enable interrupt Generation */ 805fe56b9e6SYuval Mintz qed_int_igu_enable_int(p_hwfn, p_ptt, int_mode); 806fe56b9e6SYuval Mintz 807cc875c2eSYuval Mintz /* Configure AEU signal change to produce attentions for link */ 808cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_LEADING_EDGE_LATCH, 0xfff); 809cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_TRAILING_EDGE_LATCH, 0xfff); 810cc875c2eSYuval Mintz 811fe56b9e6SYuval Mintz /* Flush the writes to IGU */ 812fe56b9e6SYuval Mintz mmiowb(); 813cc875c2eSYuval Mintz 814cc875c2eSYuval Mintz /* Unmask AEU signals toward IGU */ 815cc875c2eSYuval Mintz qed_wr(p_hwfn, p_ptt, MISC_REG_AEU_MASK_ATTN_IGU, 0xff); 816fe56b9e6SYuval Mintz } 817fe56b9e6SYuval Mintz 818fe56b9e6SYuval Mintz void qed_int_igu_disable_int(struct qed_hwfn *p_hwfn, 819fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 820fe56b9e6SYuval Mintz { 821fe56b9e6SYuval Mintz p_hwfn->b_int_enabled = 0; 822fe56b9e6SYuval Mintz 823fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_PF_CONFIGURATION, 0); 824fe56b9e6SYuval Mintz } 825fe56b9e6SYuval Mintz 826fe56b9e6SYuval Mintz #define IGU_CLEANUP_SLEEP_LENGTH (1000) 827fe56b9e6SYuval Mintz void qed_int_igu_cleanup_sb(struct qed_hwfn *p_hwfn, 828fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 829fe56b9e6SYuval Mintz u32 sb_id, 830fe56b9e6SYuval Mintz bool cleanup_set, 831fe56b9e6SYuval Mintz u16 opaque_fid 832fe56b9e6SYuval Mintz ) 833fe56b9e6SYuval Mintz { 834fe56b9e6SYuval Mintz u32 pxp_addr = IGU_CMD_INT_ACK_BASE + sb_id; 835fe56b9e6SYuval Mintz u32 sleep_cnt = IGU_CLEANUP_SLEEP_LENGTH; 836fe56b9e6SYuval Mintz u32 data = 0; 837fe56b9e6SYuval Mintz u32 cmd_ctrl = 0; 838fe56b9e6SYuval Mintz u32 val = 0; 839fe56b9e6SYuval Mintz u32 sb_bit = 0; 840fe56b9e6SYuval Mintz u32 sb_bit_addr = 0; 841fe56b9e6SYuval Mintz 842fe56b9e6SYuval Mintz /* Set the data field */ 843fe56b9e6SYuval Mintz SET_FIELD(data, IGU_CLEANUP_CLEANUP_SET, cleanup_set ? 1 : 0); 844fe56b9e6SYuval Mintz SET_FIELD(data, IGU_CLEANUP_CLEANUP_TYPE, 0); 845fe56b9e6SYuval Mintz SET_FIELD(data, IGU_CLEANUP_COMMAND_TYPE, IGU_COMMAND_TYPE_SET); 846fe56b9e6SYuval Mintz 847fe56b9e6SYuval Mintz /* Set the control register */ 848fe56b9e6SYuval Mintz SET_FIELD(cmd_ctrl, IGU_CTRL_REG_PXP_ADDR, pxp_addr); 849fe56b9e6SYuval Mintz SET_FIELD(cmd_ctrl, IGU_CTRL_REG_FID, opaque_fid); 850fe56b9e6SYuval Mintz SET_FIELD(cmd_ctrl, IGU_CTRL_REG_TYPE, IGU_CTRL_CMD_TYPE_WR); 851fe56b9e6SYuval Mintz 852fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_COMMAND_REG_32LSB_DATA, data); 853fe56b9e6SYuval Mintz 854fe56b9e6SYuval Mintz barrier(); 855fe56b9e6SYuval Mintz 856fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_COMMAND_REG_CTRL, cmd_ctrl); 857fe56b9e6SYuval Mintz 858fe56b9e6SYuval Mintz /* Flush the write to IGU */ 859fe56b9e6SYuval Mintz mmiowb(); 860fe56b9e6SYuval Mintz 861fe56b9e6SYuval Mintz /* calculate where to read the status bit from */ 862fe56b9e6SYuval Mintz sb_bit = 1 << (sb_id % 32); 863fe56b9e6SYuval Mintz sb_bit_addr = sb_id / 32 * sizeof(u32); 864fe56b9e6SYuval Mintz 865fe56b9e6SYuval Mintz sb_bit_addr += IGU_REG_CLEANUP_STATUS_0; 866fe56b9e6SYuval Mintz 867fe56b9e6SYuval Mintz /* Now wait for the command to complete */ 868fe56b9e6SYuval Mintz do { 869fe56b9e6SYuval Mintz val = qed_rd(p_hwfn, p_ptt, sb_bit_addr); 870fe56b9e6SYuval Mintz 871fe56b9e6SYuval Mintz if ((val & sb_bit) == (cleanup_set ? sb_bit : 0)) 872fe56b9e6SYuval Mintz break; 873fe56b9e6SYuval Mintz 874fe56b9e6SYuval Mintz usleep_range(5000, 10000); 875fe56b9e6SYuval Mintz } while (--sleep_cnt); 876fe56b9e6SYuval Mintz 877fe56b9e6SYuval Mintz if (!sleep_cnt) 878fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, 879fe56b9e6SYuval Mintz "Timeout waiting for clear status 0x%08x [for sb %d]\n", 880fe56b9e6SYuval Mintz val, sb_id); 881fe56b9e6SYuval Mintz } 882fe56b9e6SYuval Mintz 883fe56b9e6SYuval Mintz void qed_int_igu_init_pure_rt_single(struct qed_hwfn *p_hwfn, 884fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 885fe56b9e6SYuval Mintz u32 sb_id, 886fe56b9e6SYuval Mintz u16 opaque, 887fe56b9e6SYuval Mintz bool b_set) 888fe56b9e6SYuval Mintz { 889fe56b9e6SYuval Mintz int pi; 890fe56b9e6SYuval Mintz 891fe56b9e6SYuval Mintz /* Set */ 892fe56b9e6SYuval Mintz if (b_set) 893fe56b9e6SYuval Mintz qed_int_igu_cleanup_sb(p_hwfn, p_ptt, sb_id, 1, opaque); 894fe56b9e6SYuval Mintz 895fe56b9e6SYuval Mintz /* Clear */ 896fe56b9e6SYuval Mintz qed_int_igu_cleanup_sb(p_hwfn, p_ptt, sb_id, 0, opaque); 897fe56b9e6SYuval Mintz 898fe56b9e6SYuval Mintz /* Clear the CAU for the SB */ 899fe56b9e6SYuval Mintz for (pi = 0; pi < 12; pi++) 900fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, 901fe56b9e6SYuval Mintz CAU_REG_PI_MEMORY + (sb_id * 12 + pi) * 4, 0); 902fe56b9e6SYuval Mintz } 903fe56b9e6SYuval Mintz 904fe56b9e6SYuval Mintz void qed_int_igu_init_pure_rt(struct qed_hwfn *p_hwfn, 905fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 906fe56b9e6SYuval Mintz bool b_set, 907fe56b9e6SYuval Mintz bool b_slowpath) 908fe56b9e6SYuval Mintz { 909fe56b9e6SYuval Mintz u32 igu_base_sb = p_hwfn->hw_info.p_igu_info->igu_base_sb; 910fe56b9e6SYuval Mintz u32 igu_sb_cnt = p_hwfn->hw_info.p_igu_info->igu_sb_cnt; 911fe56b9e6SYuval Mintz u32 sb_id = 0; 912fe56b9e6SYuval Mintz u32 val = 0; 913fe56b9e6SYuval Mintz 914fe56b9e6SYuval Mintz val = qed_rd(p_hwfn, p_ptt, IGU_REG_BLOCK_CONFIGURATION); 915fe56b9e6SYuval Mintz val |= IGU_REG_BLOCK_CONFIGURATION_VF_CLEANUP_EN; 916fe56b9e6SYuval Mintz val &= ~IGU_REG_BLOCK_CONFIGURATION_PXP_TPH_INTERFACE_EN; 917fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_BLOCK_CONFIGURATION, val); 918fe56b9e6SYuval Mintz 919fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 920fe56b9e6SYuval Mintz "IGU cleaning SBs [%d,...,%d]\n", 921fe56b9e6SYuval Mintz igu_base_sb, igu_base_sb + igu_sb_cnt - 1); 922fe56b9e6SYuval Mintz 923fe56b9e6SYuval Mintz for (sb_id = igu_base_sb; sb_id < igu_base_sb + igu_sb_cnt; sb_id++) 924fe56b9e6SYuval Mintz qed_int_igu_init_pure_rt_single(p_hwfn, p_ptt, sb_id, 925fe56b9e6SYuval Mintz p_hwfn->hw_info.opaque_fid, 926fe56b9e6SYuval Mintz b_set); 927fe56b9e6SYuval Mintz 928fe56b9e6SYuval Mintz if (b_slowpath) { 929fe56b9e6SYuval Mintz sb_id = p_hwfn->hw_info.p_igu_info->igu_dsb_id; 930fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 931fe56b9e6SYuval Mintz "IGU cleaning slowpath SB [%d]\n", sb_id); 932fe56b9e6SYuval Mintz qed_int_igu_init_pure_rt_single(p_hwfn, p_ptt, sb_id, 933fe56b9e6SYuval Mintz p_hwfn->hw_info.opaque_fid, 934fe56b9e6SYuval Mintz b_set); 935fe56b9e6SYuval Mintz } 936fe56b9e6SYuval Mintz } 937fe56b9e6SYuval Mintz 938fe56b9e6SYuval Mintz int qed_int_igu_read_cam(struct qed_hwfn *p_hwfn, 939fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 940fe56b9e6SYuval Mintz { 941fe56b9e6SYuval Mintz struct qed_igu_info *p_igu_info; 942fe56b9e6SYuval Mintz struct qed_igu_block *blk; 943fe56b9e6SYuval Mintz u32 val; 944fe56b9e6SYuval Mintz u16 sb_id; 945fe56b9e6SYuval Mintz u16 prev_sb_id = 0xFF; 946fe56b9e6SYuval Mintz 947fe56b9e6SYuval Mintz p_hwfn->hw_info.p_igu_info = kzalloc(sizeof(*p_igu_info), GFP_ATOMIC); 948fe56b9e6SYuval Mintz 949fe56b9e6SYuval Mintz if (!p_hwfn->hw_info.p_igu_info) 950fe56b9e6SYuval Mintz return -ENOMEM; 951fe56b9e6SYuval Mintz 952fe56b9e6SYuval Mintz p_igu_info = p_hwfn->hw_info.p_igu_info; 953fe56b9e6SYuval Mintz 954fe56b9e6SYuval Mintz /* Initialize base sb / sb cnt for PFs */ 955fe56b9e6SYuval Mintz p_igu_info->igu_base_sb = 0xffff; 956fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt = 0; 957fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id = 0xffff; 958fe56b9e6SYuval Mintz p_igu_info->igu_base_sb_iov = 0xffff; 959fe56b9e6SYuval Mintz 960fe56b9e6SYuval Mintz for (sb_id = 0; sb_id < QED_MAPPING_MEMORY_SIZE(p_hwfn->cdev); 961fe56b9e6SYuval Mintz sb_id++) { 962fe56b9e6SYuval Mintz blk = &p_igu_info->igu_map.igu_blocks[sb_id]; 963fe56b9e6SYuval Mintz 964fe56b9e6SYuval Mintz val = qed_rd(p_hwfn, p_ptt, 965fe56b9e6SYuval Mintz IGU_REG_MAPPING_MEMORY + sizeof(u32) * sb_id); 966fe56b9e6SYuval Mintz 967fe56b9e6SYuval Mintz /* stop scanning when hit first invalid PF entry */ 968fe56b9e6SYuval Mintz if (!GET_FIELD(val, IGU_MAPPING_LINE_VALID) && 969fe56b9e6SYuval Mintz GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID)) 970fe56b9e6SYuval Mintz break; 971fe56b9e6SYuval Mintz 972fe56b9e6SYuval Mintz blk->status = QED_IGU_STATUS_VALID; 973fe56b9e6SYuval Mintz blk->function_id = GET_FIELD(val, 974fe56b9e6SYuval Mintz IGU_MAPPING_LINE_FUNCTION_NUMBER); 975fe56b9e6SYuval Mintz blk->is_pf = GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID); 976fe56b9e6SYuval Mintz blk->vector_number = GET_FIELD(val, 977fe56b9e6SYuval Mintz IGU_MAPPING_LINE_VECTOR_NUMBER); 978fe56b9e6SYuval Mintz 979fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 980fe56b9e6SYuval Mintz "IGU_BLOCK[sb_id]:%x:func_id = %d is_pf = %d vector_num = 0x%x\n", 981fe56b9e6SYuval Mintz val, blk->function_id, blk->is_pf, 982fe56b9e6SYuval Mintz blk->vector_number); 983fe56b9e6SYuval Mintz 984fe56b9e6SYuval Mintz if (blk->is_pf) { 985fe56b9e6SYuval Mintz if (blk->function_id == p_hwfn->rel_pf_id) { 986fe56b9e6SYuval Mintz blk->status |= QED_IGU_STATUS_PF; 987fe56b9e6SYuval Mintz 988fe56b9e6SYuval Mintz if (blk->vector_number == 0) { 989fe56b9e6SYuval Mintz if (p_igu_info->igu_dsb_id == 0xffff) 990fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id = sb_id; 991fe56b9e6SYuval Mintz } else { 992fe56b9e6SYuval Mintz if (p_igu_info->igu_base_sb == 993fe56b9e6SYuval Mintz 0xffff) { 994fe56b9e6SYuval Mintz p_igu_info->igu_base_sb = sb_id; 995fe56b9e6SYuval Mintz } else if (prev_sb_id != sb_id - 1) { 996fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn->cdev, 997fe56b9e6SYuval Mintz "consecutive igu vectors for HWFN %x broken", 998fe56b9e6SYuval Mintz p_hwfn->rel_pf_id); 999fe56b9e6SYuval Mintz break; 1000fe56b9e6SYuval Mintz } 1001fe56b9e6SYuval Mintz prev_sb_id = sb_id; 1002fe56b9e6SYuval Mintz /* we don't count the default */ 1003fe56b9e6SYuval Mintz (p_igu_info->igu_sb_cnt)++; 1004fe56b9e6SYuval Mintz } 1005fe56b9e6SYuval Mintz } 1006fe56b9e6SYuval Mintz } 1007fe56b9e6SYuval Mintz } 1008fe56b9e6SYuval Mintz 1009fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 1010fe56b9e6SYuval Mintz "IGU igu_base_sb=0x%x igu_sb_cnt=%d igu_dsb_id=0x%x\n", 1011fe56b9e6SYuval Mintz p_igu_info->igu_base_sb, 1012fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt, 1013fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id); 1014fe56b9e6SYuval Mintz 1015fe56b9e6SYuval Mintz if (p_igu_info->igu_base_sb == 0xffff || 1016fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id == 0xffff || 1017fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt == 0) { 1018fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, 1019fe56b9e6SYuval Mintz "IGU CAM returned invalid values igu_base_sb=0x%x igu_sb_cnt=%d igu_dsb_id=0x%x\n", 1020fe56b9e6SYuval Mintz p_igu_info->igu_base_sb, 1021fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt, 1022fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id); 1023fe56b9e6SYuval Mintz return -EINVAL; 1024fe56b9e6SYuval Mintz } 1025fe56b9e6SYuval Mintz 1026fe56b9e6SYuval Mintz return 0; 1027fe56b9e6SYuval Mintz } 1028fe56b9e6SYuval Mintz 1029fe56b9e6SYuval Mintz /** 1030fe56b9e6SYuval Mintz * @brief Initialize igu runtime registers 1031fe56b9e6SYuval Mintz * 1032fe56b9e6SYuval Mintz * @param p_hwfn 1033fe56b9e6SYuval Mintz */ 1034fe56b9e6SYuval Mintz void qed_int_igu_init_rt(struct qed_hwfn *p_hwfn) 1035fe56b9e6SYuval Mintz { 1036fe56b9e6SYuval Mintz u32 igu_pf_conf = 0; 1037fe56b9e6SYuval Mintz 1038fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_FUNC_EN; 1039fe56b9e6SYuval Mintz 1040fe56b9e6SYuval Mintz STORE_RT_REG(p_hwfn, IGU_REG_PF_CONFIGURATION_RT_OFFSET, igu_pf_conf); 1041fe56b9e6SYuval Mintz } 1042fe56b9e6SYuval Mintz 1043fe56b9e6SYuval Mintz u64 qed_int_igu_read_sisr_reg(struct qed_hwfn *p_hwfn) 1044fe56b9e6SYuval Mintz { 1045fe56b9e6SYuval Mintz u64 intr_status = 0; 1046fe56b9e6SYuval Mintz u32 intr_status_lo = 0; 1047fe56b9e6SYuval Mintz u32 intr_status_hi = 0; 1048fe56b9e6SYuval Mintz u32 lsb_igu_cmd_addr = IGU_REG_SISR_MDPC_WMASK_LSB_UPPER - 1049fe56b9e6SYuval Mintz IGU_CMD_INT_ACK_BASE; 1050fe56b9e6SYuval Mintz u32 msb_igu_cmd_addr = IGU_REG_SISR_MDPC_WMASK_MSB_UPPER - 1051fe56b9e6SYuval Mintz IGU_CMD_INT_ACK_BASE; 1052fe56b9e6SYuval Mintz 1053fe56b9e6SYuval Mintz intr_status_lo = REG_RD(p_hwfn, 1054fe56b9e6SYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 1055fe56b9e6SYuval Mintz lsb_igu_cmd_addr * 8); 1056fe56b9e6SYuval Mintz intr_status_hi = REG_RD(p_hwfn, 1057fe56b9e6SYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 1058fe56b9e6SYuval Mintz msb_igu_cmd_addr * 8); 1059fe56b9e6SYuval Mintz intr_status = ((u64)intr_status_hi << 32) + (u64)intr_status_lo; 1060fe56b9e6SYuval Mintz 1061fe56b9e6SYuval Mintz return intr_status; 1062fe56b9e6SYuval Mintz } 1063fe56b9e6SYuval Mintz 1064fe56b9e6SYuval Mintz static void qed_int_sp_dpc_setup(struct qed_hwfn *p_hwfn) 1065fe56b9e6SYuval Mintz { 1066fe56b9e6SYuval Mintz tasklet_init(p_hwfn->sp_dpc, 1067fe56b9e6SYuval Mintz qed_int_sp_dpc, (unsigned long)p_hwfn); 1068fe56b9e6SYuval Mintz p_hwfn->b_sp_dpc_enabled = true; 1069fe56b9e6SYuval Mintz } 1070fe56b9e6SYuval Mintz 1071fe56b9e6SYuval Mintz static int qed_int_sp_dpc_alloc(struct qed_hwfn *p_hwfn) 1072fe56b9e6SYuval Mintz { 1073fe56b9e6SYuval Mintz p_hwfn->sp_dpc = kmalloc(sizeof(*p_hwfn->sp_dpc), GFP_ATOMIC); 1074fe56b9e6SYuval Mintz if (!p_hwfn->sp_dpc) 1075fe56b9e6SYuval Mintz return -ENOMEM; 1076fe56b9e6SYuval Mintz 1077fe56b9e6SYuval Mintz return 0; 1078fe56b9e6SYuval Mintz } 1079fe56b9e6SYuval Mintz 1080fe56b9e6SYuval Mintz static void qed_int_sp_dpc_free(struct qed_hwfn *p_hwfn) 1081fe56b9e6SYuval Mintz { 1082fe56b9e6SYuval Mintz kfree(p_hwfn->sp_dpc); 1083fe56b9e6SYuval Mintz } 1084fe56b9e6SYuval Mintz 1085fe56b9e6SYuval Mintz int qed_int_alloc(struct qed_hwfn *p_hwfn, 1086fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 1087fe56b9e6SYuval Mintz { 1088fe56b9e6SYuval Mintz int rc = 0; 1089fe56b9e6SYuval Mintz 1090fe56b9e6SYuval Mintz rc = qed_int_sp_dpc_alloc(p_hwfn); 1091fe56b9e6SYuval Mintz if (rc) { 1092fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, "Failed to allocate sp dpc mem\n"); 1093fe56b9e6SYuval Mintz return rc; 1094fe56b9e6SYuval Mintz } 1095fe56b9e6SYuval Mintz rc = qed_int_sp_sb_alloc(p_hwfn, p_ptt); 1096fe56b9e6SYuval Mintz if (rc) { 1097fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, "Failed to allocate sp sb mem\n"); 1098fe56b9e6SYuval Mintz return rc; 1099fe56b9e6SYuval Mintz } 1100cc875c2eSYuval Mintz rc = qed_int_sb_attn_alloc(p_hwfn, p_ptt); 1101cc875c2eSYuval Mintz if (rc) { 1102cc875c2eSYuval Mintz DP_ERR(p_hwfn->cdev, "Failed to allocate sb attn mem\n"); 1103cc875c2eSYuval Mintz return rc; 1104cc875c2eSYuval Mintz } 1105fe56b9e6SYuval Mintz return rc; 1106fe56b9e6SYuval Mintz } 1107fe56b9e6SYuval Mintz 1108fe56b9e6SYuval Mintz void qed_int_free(struct qed_hwfn *p_hwfn) 1109fe56b9e6SYuval Mintz { 1110fe56b9e6SYuval Mintz qed_int_sp_sb_free(p_hwfn); 1111cc875c2eSYuval Mintz qed_int_sb_attn_free(p_hwfn); 1112fe56b9e6SYuval Mintz qed_int_sp_dpc_free(p_hwfn); 1113fe56b9e6SYuval Mintz } 1114fe56b9e6SYuval Mintz 1115fe56b9e6SYuval Mintz void qed_int_setup(struct qed_hwfn *p_hwfn, 1116fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 1117fe56b9e6SYuval Mintz { 1118fe56b9e6SYuval Mintz qed_int_sp_sb_setup(p_hwfn, p_ptt); 1119fe56b9e6SYuval Mintz qed_int_sp_dpc_setup(p_hwfn); 1120fe56b9e6SYuval Mintz } 1121fe56b9e6SYuval Mintz 1122fe56b9e6SYuval Mintz int qed_int_get_num_sbs(struct qed_hwfn *p_hwfn, 1123fe56b9e6SYuval Mintz int *p_iov_blks) 1124fe56b9e6SYuval Mintz { 1125fe56b9e6SYuval Mintz struct qed_igu_info *info = p_hwfn->hw_info.p_igu_info; 1126fe56b9e6SYuval Mintz 1127fe56b9e6SYuval Mintz if (!info) 1128fe56b9e6SYuval Mintz return 0; 1129fe56b9e6SYuval Mintz 1130fe56b9e6SYuval Mintz if (p_iov_blks) 1131fe56b9e6SYuval Mintz *p_iov_blks = info->free_blks; 1132fe56b9e6SYuval Mintz 1133fe56b9e6SYuval Mintz return info->igu_sb_cnt; 1134fe56b9e6SYuval Mintz } 1135