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 42fe56b9e6SYuval Mintz void qed_int_sp_dpc(unsigned long hwfn_cookie) 43fe56b9e6SYuval Mintz { 44fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = (struct qed_hwfn *)hwfn_cookie; 45fe56b9e6SYuval Mintz struct qed_pi_info *pi_info = NULL; 46fe56b9e6SYuval Mintz struct qed_sb_info *sb_info; 47fe56b9e6SYuval Mintz int arr_size; 48fe56b9e6SYuval Mintz u16 rc = 0; 49fe56b9e6SYuval Mintz 50fe56b9e6SYuval Mintz if (!p_hwfn) { 51fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, "DPC called - no hwfn!\n"); 52fe56b9e6SYuval Mintz return; 53fe56b9e6SYuval Mintz } 54fe56b9e6SYuval Mintz 55fe56b9e6SYuval Mintz if (!p_hwfn->p_sp_sb) { 56fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, "DPC called - no p_sp_sb\n"); 57fe56b9e6SYuval Mintz return; 58fe56b9e6SYuval Mintz } 59fe56b9e6SYuval Mintz 60fe56b9e6SYuval Mintz sb_info = &p_hwfn->p_sp_sb->sb_info; 61fe56b9e6SYuval Mintz arr_size = ARRAY_SIZE(p_hwfn->p_sp_sb->pi_info_arr); 62fe56b9e6SYuval Mintz if (!sb_info) { 63fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, 64fe56b9e6SYuval Mintz "Status block is NULL - cannot ack interrupts\n"); 65fe56b9e6SYuval Mintz return; 66fe56b9e6SYuval Mintz } 67fe56b9e6SYuval Mintz 68fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "DPC Called! (hwfn %p %d)\n", 69fe56b9e6SYuval Mintz p_hwfn, p_hwfn->my_id); 70fe56b9e6SYuval Mintz 71fe56b9e6SYuval Mintz /* Disable ack for def status block. Required both for msix + 72fe56b9e6SYuval Mintz * inta in non-mask mode, in inta does no harm. 73fe56b9e6SYuval Mintz */ 74fe56b9e6SYuval Mintz qed_sb_ack(sb_info, IGU_INT_DISABLE, 0); 75fe56b9e6SYuval Mintz 76fe56b9e6SYuval Mintz /* Gather Interrupts/Attentions information */ 77fe56b9e6SYuval Mintz if (!sb_info->sb_virt) { 78fe56b9e6SYuval Mintz DP_ERR( 79fe56b9e6SYuval Mintz p_hwfn->cdev, 80fe56b9e6SYuval Mintz "Interrupt Status block is NULL - cannot check for new interrupts!\n"); 81fe56b9e6SYuval Mintz } else { 82fe56b9e6SYuval Mintz u32 tmp_index = sb_info->sb_ack; 83fe56b9e6SYuval Mintz 84fe56b9e6SYuval Mintz rc = qed_sb_update_sb_idx(sb_info); 85fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn->cdev, NETIF_MSG_INTR, 86fe56b9e6SYuval Mintz "Interrupt indices: 0x%08x --> 0x%08x\n", 87fe56b9e6SYuval Mintz tmp_index, sb_info->sb_ack); 88fe56b9e6SYuval Mintz } 89fe56b9e6SYuval Mintz 90fe56b9e6SYuval Mintz /* Check if we expect interrupts at this time. if not just ack them */ 91fe56b9e6SYuval Mintz if (!(rc & QED_SB_EVENT_MASK)) { 92fe56b9e6SYuval Mintz qed_sb_ack(sb_info, IGU_INT_ENABLE, 1); 93fe56b9e6SYuval Mintz return; 94fe56b9e6SYuval Mintz } 95fe56b9e6SYuval Mintz 96fe56b9e6SYuval Mintz /* Check the validity of the DPC ptt. If not ack interrupts and fail */ 97fe56b9e6SYuval Mintz if (!p_hwfn->p_dpc_ptt) { 98fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn->cdev, "Failed to allocate PTT\n"); 99fe56b9e6SYuval Mintz qed_sb_ack(sb_info, IGU_INT_ENABLE, 1); 100fe56b9e6SYuval Mintz return; 101fe56b9e6SYuval Mintz } 102fe56b9e6SYuval Mintz 103fe56b9e6SYuval Mintz if (rc & QED_SB_IDX) { 104fe56b9e6SYuval Mintz int pi; 105fe56b9e6SYuval Mintz 106fe56b9e6SYuval Mintz /* Look for a free index */ 107fe56b9e6SYuval Mintz for (pi = 0; pi < arr_size; pi++) { 108fe56b9e6SYuval Mintz pi_info = &p_hwfn->p_sp_sb->pi_info_arr[pi]; 109fe56b9e6SYuval Mintz if (pi_info->comp_cb) 110fe56b9e6SYuval Mintz pi_info->comp_cb(p_hwfn, pi_info->cookie); 111fe56b9e6SYuval Mintz } 112fe56b9e6SYuval Mintz } 113fe56b9e6SYuval Mintz 114fe56b9e6SYuval Mintz qed_sb_ack(sb_info, IGU_INT_ENABLE, 1); 115fe56b9e6SYuval Mintz } 116fe56b9e6SYuval Mintz 117fe56b9e6SYuval Mintz /* coalescing timeout = timeset << (timer_res + 1) */ 118fe56b9e6SYuval Mintz #define QED_CAU_DEF_RX_USECS 24 119fe56b9e6SYuval Mintz #define QED_CAU_DEF_TX_USECS 48 120fe56b9e6SYuval Mintz 121fe56b9e6SYuval Mintz void qed_init_cau_sb_entry(struct qed_hwfn *p_hwfn, 122fe56b9e6SYuval Mintz struct cau_sb_entry *p_sb_entry, 123fe56b9e6SYuval Mintz u8 pf_id, 124fe56b9e6SYuval Mintz u16 vf_number, 125fe56b9e6SYuval Mintz u8 vf_valid) 126fe56b9e6SYuval Mintz { 127fe56b9e6SYuval Mintz u32 cau_state; 128fe56b9e6SYuval Mintz 129fe56b9e6SYuval Mintz memset(p_sb_entry, 0, sizeof(*p_sb_entry)); 130fe56b9e6SYuval Mintz 131fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_PF_NUMBER, pf_id); 132fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_VF_NUMBER, vf_number); 133fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_VF_VALID, vf_valid); 134fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_SB_TIMESET0, 0x7F); 135fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_SB_TIMESET1, 0x7F); 136fe56b9e6SYuval Mintz 137fe56b9e6SYuval Mintz /* setting the time resultion to a fixed value ( = 1) */ 138fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_TIMER_RES0, 139fe56b9e6SYuval Mintz QED_CAU_DEF_RX_TIMER_RES); 140fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_TIMER_RES1, 141fe56b9e6SYuval Mintz QED_CAU_DEF_TX_TIMER_RES); 142fe56b9e6SYuval Mintz 143fe56b9e6SYuval Mintz cau_state = CAU_HC_DISABLE_STATE; 144fe56b9e6SYuval Mintz 145fe56b9e6SYuval Mintz if (p_hwfn->cdev->int_coalescing_mode == QED_COAL_MODE_ENABLE) { 146fe56b9e6SYuval Mintz cau_state = CAU_HC_ENABLE_STATE; 147fe56b9e6SYuval Mintz if (!p_hwfn->cdev->rx_coalesce_usecs) 148fe56b9e6SYuval Mintz p_hwfn->cdev->rx_coalesce_usecs = 149fe56b9e6SYuval Mintz QED_CAU_DEF_RX_USECS; 150fe56b9e6SYuval Mintz if (!p_hwfn->cdev->tx_coalesce_usecs) 151fe56b9e6SYuval Mintz p_hwfn->cdev->tx_coalesce_usecs = 152fe56b9e6SYuval Mintz QED_CAU_DEF_TX_USECS; 153fe56b9e6SYuval Mintz } 154fe56b9e6SYuval Mintz 155fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->data, CAU_SB_ENTRY_STATE0, cau_state); 156fe56b9e6SYuval Mintz SET_FIELD(p_sb_entry->data, CAU_SB_ENTRY_STATE1, cau_state); 157fe56b9e6SYuval Mintz } 158fe56b9e6SYuval Mintz 159fe56b9e6SYuval Mintz void qed_int_cau_conf_sb(struct qed_hwfn *p_hwfn, 160fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 161fe56b9e6SYuval Mintz dma_addr_t sb_phys, 162fe56b9e6SYuval Mintz u16 igu_sb_id, 163fe56b9e6SYuval Mintz u16 vf_number, 164fe56b9e6SYuval Mintz u8 vf_valid) 165fe56b9e6SYuval Mintz { 166fe56b9e6SYuval Mintz struct cau_sb_entry sb_entry; 167fe56b9e6SYuval Mintz u32 val; 168fe56b9e6SYuval Mintz 169fe56b9e6SYuval Mintz qed_init_cau_sb_entry(p_hwfn, &sb_entry, p_hwfn->rel_pf_id, 170fe56b9e6SYuval Mintz vf_number, vf_valid); 171fe56b9e6SYuval Mintz 172fe56b9e6SYuval Mintz if (p_hwfn->hw_init_done) { 173fe56b9e6SYuval Mintz val = CAU_REG_SB_ADDR_MEMORY + igu_sb_id * sizeof(u64); 174fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, val, lower_32_bits(sb_phys)); 175fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, val + sizeof(u32), 176fe56b9e6SYuval Mintz upper_32_bits(sb_phys)); 177fe56b9e6SYuval Mintz 178fe56b9e6SYuval Mintz val = CAU_REG_SB_VAR_MEMORY + igu_sb_id * sizeof(u64); 179fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, val, sb_entry.data); 180fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, val + sizeof(u32), sb_entry.params); 181fe56b9e6SYuval Mintz } else { 182fe56b9e6SYuval Mintz /* Initialize Status Block Address */ 183fe56b9e6SYuval Mintz STORE_RT_REG_AGG(p_hwfn, 184fe56b9e6SYuval Mintz CAU_REG_SB_ADDR_MEMORY_RT_OFFSET + 185fe56b9e6SYuval Mintz igu_sb_id * 2, 186fe56b9e6SYuval Mintz sb_phys); 187fe56b9e6SYuval Mintz 188fe56b9e6SYuval Mintz STORE_RT_REG_AGG(p_hwfn, 189fe56b9e6SYuval Mintz CAU_REG_SB_VAR_MEMORY_RT_OFFSET + 190fe56b9e6SYuval Mintz igu_sb_id * 2, 191fe56b9e6SYuval Mintz sb_entry); 192fe56b9e6SYuval Mintz } 193fe56b9e6SYuval Mintz 194fe56b9e6SYuval Mintz /* Configure pi coalescing if set */ 195fe56b9e6SYuval Mintz if (p_hwfn->cdev->int_coalescing_mode == QED_COAL_MODE_ENABLE) { 196fe56b9e6SYuval Mintz u8 timeset = p_hwfn->cdev->rx_coalesce_usecs >> 197fe56b9e6SYuval Mintz (QED_CAU_DEF_RX_TIMER_RES + 1); 198fe56b9e6SYuval Mintz u8 num_tc = 1, i; 199fe56b9e6SYuval Mintz 200fe56b9e6SYuval Mintz qed_int_cau_conf_pi(p_hwfn, p_ptt, igu_sb_id, RX_PI, 201fe56b9e6SYuval Mintz QED_COAL_RX_STATE_MACHINE, 202fe56b9e6SYuval Mintz timeset); 203fe56b9e6SYuval Mintz 204fe56b9e6SYuval Mintz timeset = p_hwfn->cdev->tx_coalesce_usecs >> 205fe56b9e6SYuval Mintz (QED_CAU_DEF_TX_TIMER_RES + 1); 206fe56b9e6SYuval Mintz 207fe56b9e6SYuval Mintz for (i = 0; i < num_tc; i++) { 208fe56b9e6SYuval Mintz qed_int_cau_conf_pi(p_hwfn, p_ptt, 209fe56b9e6SYuval Mintz igu_sb_id, TX_PI(i), 210fe56b9e6SYuval Mintz QED_COAL_TX_STATE_MACHINE, 211fe56b9e6SYuval Mintz timeset); 212fe56b9e6SYuval Mintz } 213fe56b9e6SYuval Mintz } 214fe56b9e6SYuval Mintz } 215fe56b9e6SYuval Mintz 216fe56b9e6SYuval Mintz void qed_int_cau_conf_pi(struct qed_hwfn *p_hwfn, 217fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 218fe56b9e6SYuval Mintz u16 igu_sb_id, 219fe56b9e6SYuval Mintz u32 pi_index, 220fe56b9e6SYuval Mintz enum qed_coalescing_fsm coalescing_fsm, 221fe56b9e6SYuval Mintz u8 timeset) 222fe56b9e6SYuval Mintz { 223fe56b9e6SYuval Mintz struct cau_pi_entry pi_entry; 224fe56b9e6SYuval Mintz u32 sb_offset; 225fe56b9e6SYuval Mintz u32 pi_offset; 226fe56b9e6SYuval Mintz 227fe56b9e6SYuval Mintz sb_offset = igu_sb_id * PIS_PER_SB; 228fe56b9e6SYuval Mintz memset(&pi_entry, 0, sizeof(struct cau_pi_entry)); 229fe56b9e6SYuval Mintz 230fe56b9e6SYuval Mintz SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_PI_TIMESET, timeset); 231fe56b9e6SYuval Mintz if (coalescing_fsm == QED_COAL_RX_STATE_MACHINE) 232fe56b9e6SYuval Mintz SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_FSM_SEL, 0); 233fe56b9e6SYuval Mintz else 234fe56b9e6SYuval Mintz SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_FSM_SEL, 1); 235fe56b9e6SYuval Mintz 236fe56b9e6SYuval Mintz pi_offset = sb_offset + pi_index; 237fe56b9e6SYuval Mintz if (p_hwfn->hw_init_done) { 238fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, 239fe56b9e6SYuval Mintz CAU_REG_PI_MEMORY + pi_offset * sizeof(u32), 240fe56b9e6SYuval Mintz *((u32 *)&(pi_entry))); 241fe56b9e6SYuval Mintz } else { 242fe56b9e6SYuval Mintz STORE_RT_REG(p_hwfn, 243fe56b9e6SYuval Mintz CAU_REG_PI_MEMORY_RT_OFFSET + pi_offset, 244fe56b9e6SYuval Mintz *((u32 *)&(pi_entry))); 245fe56b9e6SYuval Mintz } 246fe56b9e6SYuval Mintz } 247fe56b9e6SYuval Mintz 248fe56b9e6SYuval Mintz void qed_int_sb_setup(struct qed_hwfn *p_hwfn, 249fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 250fe56b9e6SYuval Mintz struct qed_sb_info *sb_info) 251fe56b9e6SYuval Mintz { 252fe56b9e6SYuval Mintz /* zero status block and ack counter */ 253fe56b9e6SYuval Mintz sb_info->sb_ack = 0; 254fe56b9e6SYuval Mintz memset(sb_info->sb_virt, 0, sizeof(*sb_info->sb_virt)); 255fe56b9e6SYuval Mintz 256fe56b9e6SYuval Mintz qed_int_cau_conf_sb(p_hwfn, p_ptt, sb_info->sb_phys, 257fe56b9e6SYuval Mintz sb_info->igu_sb_id, 0, 0); 258fe56b9e6SYuval Mintz } 259fe56b9e6SYuval Mintz 260fe56b9e6SYuval Mintz /** 261fe56b9e6SYuval Mintz * @brief qed_get_igu_sb_id - given a sw sb_id return the 262fe56b9e6SYuval Mintz * igu_sb_id 263fe56b9e6SYuval Mintz * 264fe56b9e6SYuval Mintz * @param p_hwfn 265fe56b9e6SYuval Mintz * @param sb_id 266fe56b9e6SYuval Mintz * 267fe56b9e6SYuval Mintz * @return u16 268fe56b9e6SYuval Mintz */ 269fe56b9e6SYuval Mintz static u16 qed_get_igu_sb_id(struct qed_hwfn *p_hwfn, 270fe56b9e6SYuval Mintz u16 sb_id) 271fe56b9e6SYuval Mintz { 272fe56b9e6SYuval Mintz u16 igu_sb_id; 273fe56b9e6SYuval Mintz 274fe56b9e6SYuval Mintz /* Assuming continuous set of IGU SBs dedicated for given PF */ 275fe56b9e6SYuval Mintz if (sb_id == QED_SP_SB_ID) 276fe56b9e6SYuval Mintz igu_sb_id = p_hwfn->hw_info.p_igu_info->igu_dsb_id; 277fe56b9e6SYuval Mintz else 278fe56b9e6SYuval Mintz igu_sb_id = sb_id + p_hwfn->hw_info.p_igu_info->igu_base_sb; 279fe56b9e6SYuval Mintz 280fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "SB [%s] index is 0x%04x\n", 281fe56b9e6SYuval Mintz (sb_id == QED_SP_SB_ID) ? "DSB" : "non-DSB", igu_sb_id); 282fe56b9e6SYuval Mintz 283fe56b9e6SYuval Mintz return igu_sb_id; 284fe56b9e6SYuval Mintz } 285fe56b9e6SYuval Mintz 286fe56b9e6SYuval Mintz int qed_int_sb_init(struct qed_hwfn *p_hwfn, 287fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 288fe56b9e6SYuval Mintz struct qed_sb_info *sb_info, 289fe56b9e6SYuval Mintz void *sb_virt_addr, 290fe56b9e6SYuval Mintz dma_addr_t sb_phy_addr, 291fe56b9e6SYuval Mintz u16 sb_id) 292fe56b9e6SYuval Mintz { 293fe56b9e6SYuval Mintz sb_info->sb_virt = sb_virt_addr; 294fe56b9e6SYuval Mintz sb_info->sb_phys = sb_phy_addr; 295fe56b9e6SYuval Mintz 296fe56b9e6SYuval Mintz sb_info->igu_sb_id = qed_get_igu_sb_id(p_hwfn, sb_id); 297fe56b9e6SYuval Mintz 298fe56b9e6SYuval Mintz if (sb_id != QED_SP_SB_ID) { 299fe56b9e6SYuval Mintz p_hwfn->sbs_info[sb_id] = sb_info; 300fe56b9e6SYuval Mintz p_hwfn->num_sbs++; 301fe56b9e6SYuval Mintz } 302fe56b9e6SYuval Mintz 303fe56b9e6SYuval Mintz sb_info->cdev = p_hwfn->cdev; 304fe56b9e6SYuval Mintz 305fe56b9e6SYuval Mintz /* The igu address will hold the absolute address that needs to be 306fe56b9e6SYuval Mintz * written to for a specific status block 307fe56b9e6SYuval Mintz */ 308fe56b9e6SYuval Mintz sb_info->igu_addr = (u8 __iomem *)p_hwfn->regview + 309fe56b9e6SYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 310fe56b9e6SYuval Mintz (sb_info->igu_sb_id << 3); 311fe56b9e6SYuval Mintz 312fe56b9e6SYuval Mintz sb_info->flags |= QED_SB_INFO_INIT; 313fe56b9e6SYuval Mintz 314fe56b9e6SYuval Mintz qed_int_sb_setup(p_hwfn, p_ptt, sb_info); 315fe56b9e6SYuval Mintz 316fe56b9e6SYuval Mintz return 0; 317fe56b9e6SYuval Mintz } 318fe56b9e6SYuval Mintz 319fe56b9e6SYuval Mintz int qed_int_sb_release(struct qed_hwfn *p_hwfn, 320fe56b9e6SYuval Mintz struct qed_sb_info *sb_info, 321fe56b9e6SYuval Mintz u16 sb_id) 322fe56b9e6SYuval Mintz { 323fe56b9e6SYuval Mintz if (sb_id == QED_SP_SB_ID) { 324fe56b9e6SYuval Mintz DP_ERR(p_hwfn, "Do Not free sp sb using this function"); 325fe56b9e6SYuval Mintz return -EINVAL; 326fe56b9e6SYuval Mintz } 327fe56b9e6SYuval Mintz 328fe56b9e6SYuval Mintz /* zero status block and ack counter */ 329fe56b9e6SYuval Mintz sb_info->sb_ack = 0; 330fe56b9e6SYuval Mintz memset(sb_info->sb_virt, 0, sizeof(*sb_info->sb_virt)); 331fe56b9e6SYuval Mintz 332fe56b9e6SYuval Mintz p_hwfn->sbs_info[sb_id] = NULL; 333fe56b9e6SYuval Mintz p_hwfn->num_sbs--; 334fe56b9e6SYuval Mintz 335fe56b9e6SYuval Mintz return 0; 336fe56b9e6SYuval Mintz } 337fe56b9e6SYuval Mintz 338fe56b9e6SYuval Mintz static void qed_int_sp_sb_free(struct qed_hwfn *p_hwfn) 339fe56b9e6SYuval Mintz { 340fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sb = p_hwfn->p_sp_sb; 341fe56b9e6SYuval Mintz 342fe56b9e6SYuval Mintz if (p_sb) { 343fe56b9e6SYuval Mintz if (p_sb->sb_info.sb_virt) 344fe56b9e6SYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 345fe56b9e6SYuval Mintz SB_ALIGNED_SIZE(p_hwfn), 346fe56b9e6SYuval Mintz p_sb->sb_info.sb_virt, 347fe56b9e6SYuval Mintz p_sb->sb_info.sb_phys); 348fe56b9e6SYuval Mintz kfree(p_sb); 349fe56b9e6SYuval Mintz } 350fe56b9e6SYuval Mintz } 351fe56b9e6SYuval Mintz 352fe56b9e6SYuval Mintz static int qed_int_sp_sb_alloc(struct qed_hwfn *p_hwfn, 353fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 354fe56b9e6SYuval Mintz { 355fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sb; 356fe56b9e6SYuval Mintz dma_addr_t p_phys = 0; 357fe56b9e6SYuval Mintz void *p_virt; 358fe56b9e6SYuval Mintz 359fe56b9e6SYuval Mintz /* SB struct */ 360fe56b9e6SYuval Mintz p_sb = kmalloc(sizeof(*p_sb), GFP_ATOMIC); 361fe56b9e6SYuval Mintz if (!p_sb) { 362fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, "Failed to allocate `struct qed_sb_info'\n"); 363fe56b9e6SYuval Mintz return -ENOMEM; 364fe56b9e6SYuval Mintz } 365fe56b9e6SYuval Mintz 366fe56b9e6SYuval Mintz /* SB ring */ 367fe56b9e6SYuval Mintz p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 368fe56b9e6SYuval Mintz SB_ALIGNED_SIZE(p_hwfn), 369fe56b9e6SYuval Mintz &p_phys, GFP_KERNEL); 370fe56b9e6SYuval Mintz if (!p_virt) { 371fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, "Failed to allocate status block\n"); 372fe56b9e6SYuval Mintz kfree(p_sb); 373fe56b9e6SYuval Mintz return -ENOMEM; 374fe56b9e6SYuval Mintz } 375fe56b9e6SYuval Mintz 376fe56b9e6SYuval Mintz /* Status Block setup */ 377fe56b9e6SYuval Mintz p_hwfn->p_sp_sb = p_sb; 378fe56b9e6SYuval Mintz qed_int_sb_init(p_hwfn, p_ptt, &p_sb->sb_info, p_virt, 379fe56b9e6SYuval Mintz p_phys, QED_SP_SB_ID); 380fe56b9e6SYuval Mintz 381fe56b9e6SYuval Mintz memset(p_sb->pi_info_arr, 0, sizeof(p_sb->pi_info_arr)); 382fe56b9e6SYuval Mintz 383fe56b9e6SYuval Mintz return 0; 384fe56b9e6SYuval Mintz } 385fe56b9e6SYuval Mintz 386fe56b9e6SYuval Mintz static void qed_int_sp_sb_setup(struct qed_hwfn *p_hwfn, 387fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 388fe56b9e6SYuval Mintz { 389fe56b9e6SYuval Mintz if (!p_hwfn) 390fe56b9e6SYuval Mintz return; 391fe56b9e6SYuval Mintz 392fe56b9e6SYuval Mintz if (p_hwfn->p_sp_sb) 393fe56b9e6SYuval Mintz qed_int_sb_setup(p_hwfn, p_ptt, &p_hwfn->p_sp_sb->sb_info); 394fe56b9e6SYuval Mintz else 395fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn->cdev, 396fe56b9e6SYuval Mintz "Failed to setup Slow path status block - NULL pointer\n"); 397fe56b9e6SYuval Mintz } 398fe56b9e6SYuval Mintz 399fe56b9e6SYuval Mintz int qed_int_register_cb(struct qed_hwfn *p_hwfn, 400fe56b9e6SYuval Mintz qed_int_comp_cb_t comp_cb, 401fe56b9e6SYuval Mintz void *cookie, 402fe56b9e6SYuval Mintz u8 *sb_idx, 403fe56b9e6SYuval Mintz __le16 **p_fw_cons) 404fe56b9e6SYuval Mintz { 405fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sp_sb = p_hwfn->p_sp_sb; 406fe56b9e6SYuval Mintz int qed_status = -ENOMEM; 407fe56b9e6SYuval Mintz u8 pi; 408fe56b9e6SYuval Mintz 409fe56b9e6SYuval Mintz /* Look for a free index */ 410fe56b9e6SYuval Mintz for (pi = 0; pi < ARRAY_SIZE(p_sp_sb->pi_info_arr); pi++) { 411fe56b9e6SYuval Mintz if (!p_sp_sb->pi_info_arr[pi].comp_cb) { 412fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].comp_cb = comp_cb; 413fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].cookie = cookie; 414fe56b9e6SYuval Mintz *sb_idx = pi; 415fe56b9e6SYuval Mintz *p_fw_cons = &p_sp_sb->sb_info.sb_virt->pi_array[pi]; 416fe56b9e6SYuval Mintz qed_status = 0; 417fe56b9e6SYuval Mintz break; 418fe56b9e6SYuval Mintz } 419fe56b9e6SYuval Mintz } 420fe56b9e6SYuval Mintz 421fe56b9e6SYuval Mintz return qed_status; 422fe56b9e6SYuval Mintz } 423fe56b9e6SYuval Mintz 424fe56b9e6SYuval Mintz int qed_int_unregister_cb(struct qed_hwfn *p_hwfn, u8 pi) 425fe56b9e6SYuval Mintz { 426fe56b9e6SYuval Mintz struct qed_sb_sp_info *p_sp_sb = p_hwfn->p_sp_sb; 427fe56b9e6SYuval Mintz int qed_status = -ENOMEM; 428fe56b9e6SYuval Mintz 429fe56b9e6SYuval Mintz if (p_sp_sb->pi_info_arr[pi].comp_cb) { 430fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].comp_cb = NULL; 431fe56b9e6SYuval Mintz p_sp_sb->pi_info_arr[pi].cookie = NULL; 432fe56b9e6SYuval Mintz qed_status = 0; 433fe56b9e6SYuval Mintz } 434fe56b9e6SYuval Mintz 435fe56b9e6SYuval Mintz return qed_status; 436fe56b9e6SYuval Mintz } 437fe56b9e6SYuval Mintz 438fe56b9e6SYuval Mintz u16 qed_int_get_sp_sb_id(struct qed_hwfn *p_hwfn) 439fe56b9e6SYuval Mintz { 440fe56b9e6SYuval Mintz return p_hwfn->p_sp_sb->sb_info.igu_sb_id; 441fe56b9e6SYuval Mintz } 442fe56b9e6SYuval Mintz 443fe56b9e6SYuval Mintz void qed_int_igu_enable_int(struct qed_hwfn *p_hwfn, 444fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 445fe56b9e6SYuval Mintz enum qed_int_mode int_mode) 446fe56b9e6SYuval Mintz { 447fe56b9e6SYuval Mintz u32 igu_pf_conf = IGU_PF_CONF_FUNC_EN; 448fe56b9e6SYuval Mintz 449fe56b9e6SYuval Mintz p_hwfn->cdev->int_mode = int_mode; 450fe56b9e6SYuval Mintz switch (p_hwfn->cdev->int_mode) { 451fe56b9e6SYuval Mintz case QED_INT_MODE_INTA: 452fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_INT_LINE_EN; 453fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_SINGLE_ISR_EN; 454fe56b9e6SYuval Mintz break; 455fe56b9e6SYuval Mintz 456fe56b9e6SYuval Mintz case QED_INT_MODE_MSI: 457fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_MSI_MSIX_EN; 458fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_SINGLE_ISR_EN; 459fe56b9e6SYuval Mintz break; 460fe56b9e6SYuval Mintz 461fe56b9e6SYuval Mintz case QED_INT_MODE_MSIX: 462fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_MSI_MSIX_EN; 463fe56b9e6SYuval Mintz break; 464fe56b9e6SYuval Mintz case QED_INT_MODE_POLL: 465fe56b9e6SYuval Mintz break; 466fe56b9e6SYuval Mintz } 467fe56b9e6SYuval Mintz 468fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_PF_CONFIGURATION, igu_pf_conf); 469fe56b9e6SYuval Mintz } 470fe56b9e6SYuval Mintz 471fe56b9e6SYuval Mintz void qed_int_igu_enable(struct qed_hwfn *p_hwfn, 472fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 473fe56b9e6SYuval Mintz enum qed_int_mode int_mode) 474fe56b9e6SYuval Mintz { 475fe56b9e6SYuval Mintz int i; 476fe56b9e6SYuval Mintz 477fe56b9e6SYuval Mintz p_hwfn->b_int_enabled = 1; 478fe56b9e6SYuval Mintz 479fe56b9e6SYuval Mintz /* Mask non-link attentions */ 480fe56b9e6SYuval Mintz for (i = 0; i < 9; i++) 481fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, 482fe56b9e6SYuval Mintz MISC_REG_AEU_ENABLE1_IGU_OUT_0 + (i << 2), 0); 483fe56b9e6SYuval Mintz 484fe56b9e6SYuval Mintz /* Enable interrupt Generation */ 485fe56b9e6SYuval Mintz qed_int_igu_enable_int(p_hwfn, p_ptt, int_mode); 486fe56b9e6SYuval Mintz 487fe56b9e6SYuval Mintz /* Flush the writes to IGU */ 488fe56b9e6SYuval Mintz mmiowb(); 489fe56b9e6SYuval Mintz } 490fe56b9e6SYuval Mintz 491fe56b9e6SYuval Mintz void qed_int_igu_disable_int(struct qed_hwfn *p_hwfn, 492fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 493fe56b9e6SYuval Mintz { 494fe56b9e6SYuval Mintz p_hwfn->b_int_enabled = 0; 495fe56b9e6SYuval Mintz 496fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_PF_CONFIGURATION, 0); 497fe56b9e6SYuval Mintz } 498fe56b9e6SYuval Mintz 499fe56b9e6SYuval Mintz #define IGU_CLEANUP_SLEEP_LENGTH (1000) 500fe56b9e6SYuval Mintz void qed_int_igu_cleanup_sb(struct qed_hwfn *p_hwfn, 501fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 502fe56b9e6SYuval Mintz u32 sb_id, 503fe56b9e6SYuval Mintz bool cleanup_set, 504fe56b9e6SYuval Mintz u16 opaque_fid 505fe56b9e6SYuval Mintz ) 506fe56b9e6SYuval Mintz { 507fe56b9e6SYuval Mintz u32 pxp_addr = IGU_CMD_INT_ACK_BASE + sb_id; 508fe56b9e6SYuval Mintz u32 sleep_cnt = IGU_CLEANUP_SLEEP_LENGTH; 509fe56b9e6SYuval Mintz u32 data = 0; 510fe56b9e6SYuval Mintz u32 cmd_ctrl = 0; 511fe56b9e6SYuval Mintz u32 val = 0; 512fe56b9e6SYuval Mintz u32 sb_bit = 0; 513fe56b9e6SYuval Mintz u32 sb_bit_addr = 0; 514fe56b9e6SYuval Mintz 515fe56b9e6SYuval Mintz /* Set the data field */ 516fe56b9e6SYuval Mintz SET_FIELD(data, IGU_CLEANUP_CLEANUP_SET, cleanup_set ? 1 : 0); 517fe56b9e6SYuval Mintz SET_FIELD(data, IGU_CLEANUP_CLEANUP_TYPE, 0); 518fe56b9e6SYuval Mintz SET_FIELD(data, IGU_CLEANUP_COMMAND_TYPE, IGU_COMMAND_TYPE_SET); 519fe56b9e6SYuval Mintz 520fe56b9e6SYuval Mintz /* Set the control register */ 521fe56b9e6SYuval Mintz SET_FIELD(cmd_ctrl, IGU_CTRL_REG_PXP_ADDR, pxp_addr); 522fe56b9e6SYuval Mintz SET_FIELD(cmd_ctrl, IGU_CTRL_REG_FID, opaque_fid); 523fe56b9e6SYuval Mintz SET_FIELD(cmd_ctrl, IGU_CTRL_REG_TYPE, IGU_CTRL_CMD_TYPE_WR); 524fe56b9e6SYuval Mintz 525fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_COMMAND_REG_32LSB_DATA, data); 526fe56b9e6SYuval Mintz 527fe56b9e6SYuval Mintz barrier(); 528fe56b9e6SYuval Mintz 529fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_COMMAND_REG_CTRL, cmd_ctrl); 530fe56b9e6SYuval Mintz 531fe56b9e6SYuval Mintz /* Flush the write to IGU */ 532fe56b9e6SYuval Mintz mmiowb(); 533fe56b9e6SYuval Mintz 534fe56b9e6SYuval Mintz /* calculate where to read the status bit from */ 535fe56b9e6SYuval Mintz sb_bit = 1 << (sb_id % 32); 536fe56b9e6SYuval Mintz sb_bit_addr = sb_id / 32 * sizeof(u32); 537fe56b9e6SYuval Mintz 538fe56b9e6SYuval Mintz sb_bit_addr += IGU_REG_CLEANUP_STATUS_0; 539fe56b9e6SYuval Mintz 540fe56b9e6SYuval Mintz /* Now wait for the command to complete */ 541fe56b9e6SYuval Mintz do { 542fe56b9e6SYuval Mintz val = qed_rd(p_hwfn, p_ptt, sb_bit_addr); 543fe56b9e6SYuval Mintz 544fe56b9e6SYuval Mintz if ((val & sb_bit) == (cleanup_set ? sb_bit : 0)) 545fe56b9e6SYuval Mintz break; 546fe56b9e6SYuval Mintz 547fe56b9e6SYuval Mintz usleep_range(5000, 10000); 548fe56b9e6SYuval Mintz } while (--sleep_cnt); 549fe56b9e6SYuval Mintz 550fe56b9e6SYuval Mintz if (!sleep_cnt) 551fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, 552fe56b9e6SYuval Mintz "Timeout waiting for clear status 0x%08x [for sb %d]\n", 553fe56b9e6SYuval Mintz val, sb_id); 554fe56b9e6SYuval Mintz } 555fe56b9e6SYuval Mintz 556fe56b9e6SYuval Mintz void qed_int_igu_init_pure_rt_single(struct qed_hwfn *p_hwfn, 557fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 558fe56b9e6SYuval Mintz u32 sb_id, 559fe56b9e6SYuval Mintz u16 opaque, 560fe56b9e6SYuval Mintz bool b_set) 561fe56b9e6SYuval Mintz { 562fe56b9e6SYuval Mintz int pi; 563fe56b9e6SYuval Mintz 564fe56b9e6SYuval Mintz /* Set */ 565fe56b9e6SYuval Mintz if (b_set) 566fe56b9e6SYuval Mintz qed_int_igu_cleanup_sb(p_hwfn, p_ptt, sb_id, 1, opaque); 567fe56b9e6SYuval Mintz 568fe56b9e6SYuval Mintz /* Clear */ 569fe56b9e6SYuval Mintz qed_int_igu_cleanup_sb(p_hwfn, p_ptt, sb_id, 0, opaque); 570fe56b9e6SYuval Mintz 571fe56b9e6SYuval Mintz /* Clear the CAU for the SB */ 572fe56b9e6SYuval Mintz for (pi = 0; pi < 12; pi++) 573fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, 574fe56b9e6SYuval Mintz CAU_REG_PI_MEMORY + (sb_id * 12 + pi) * 4, 0); 575fe56b9e6SYuval Mintz } 576fe56b9e6SYuval Mintz 577fe56b9e6SYuval Mintz void qed_int_igu_init_pure_rt(struct qed_hwfn *p_hwfn, 578fe56b9e6SYuval Mintz struct qed_ptt *p_ptt, 579fe56b9e6SYuval Mintz bool b_set, 580fe56b9e6SYuval Mintz bool b_slowpath) 581fe56b9e6SYuval Mintz { 582fe56b9e6SYuval Mintz u32 igu_base_sb = p_hwfn->hw_info.p_igu_info->igu_base_sb; 583fe56b9e6SYuval Mintz u32 igu_sb_cnt = p_hwfn->hw_info.p_igu_info->igu_sb_cnt; 584fe56b9e6SYuval Mintz u32 sb_id = 0; 585fe56b9e6SYuval Mintz u32 val = 0; 586fe56b9e6SYuval Mintz 587fe56b9e6SYuval Mintz val = qed_rd(p_hwfn, p_ptt, IGU_REG_BLOCK_CONFIGURATION); 588fe56b9e6SYuval Mintz val |= IGU_REG_BLOCK_CONFIGURATION_VF_CLEANUP_EN; 589fe56b9e6SYuval Mintz val &= ~IGU_REG_BLOCK_CONFIGURATION_PXP_TPH_INTERFACE_EN; 590fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_BLOCK_CONFIGURATION, val); 591fe56b9e6SYuval Mintz 592fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 593fe56b9e6SYuval Mintz "IGU cleaning SBs [%d,...,%d]\n", 594fe56b9e6SYuval Mintz igu_base_sb, igu_base_sb + igu_sb_cnt - 1); 595fe56b9e6SYuval Mintz 596fe56b9e6SYuval Mintz for (sb_id = igu_base_sb; sb_id < igu_base_sb + igu_sb_cnt; sb_id++) 597fe56b9e6SYuval Mintz qed_int_igu_init_pure_rt_single(p_hwfn, p_ptt, sb_id, 598fe56b9e6SYuval Mintz p_hwfn->hw_info.opaque_fid, 599fe56b9e6SYuval Mintz b_set); 600fe56b9e6SYuval Mintz 601fe56b9e6SYuval Mintz if (b_slowpath) { 602fe56b9e6SYuval Mintz sb_id = p_hwfn->hw_info.p_igu_info->igu_dsb_id; 603fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 604fe56b9e6SYuval Mintz "IGU cleaning slowpath SB [%d]\n", sb_id); 605fe56b9e6SYuval Mintz qed_int_igu_init_pure_rt_single(p_hwfn, p_ptt, sb_id, 606fe56b9e6SYuval Mintz p_hwfn->hw_info.opaque_fid, 607fe56b9e6SYuval Mintz b_set); 608fe56b9e6SYuval Mintz } 609fe56b9e6SYuval Mintz } 610fe56b9e6SYuval Mintz 611fe56b9e6SYuval Mintz int qed_int_igu_read_cam(struct qed_hwfn *p_hwfn, 612fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 613fe56b9e6SYuval Mintz { 614fe56b9e6SYuval Mintz struct qed_igu_info *p_igu_info; 615fe56b9e6SYuval Mintz struct qed_igu_block *blk; 616fe56b9e6SYuval Mintz u32 val; 617fe56b9e6SYuval Mintz u16 sb_id; 618fe56b9e6SYuval Mintz u16 prev_sb_id = 0xFF; 619fe56b9e6SYuval Mintz 620fe56b9e6SYuval Mintz p_hwfn->hw_info.p_igu_info = kzalloc(sizeof(*p_igu_info), GFP_ATOMIC); 621fe56b9e6SYuval Mintz 622fe56b9e6SYuval Mintz if (!p_hwfn->hw_info.p_igu_info) 623fe56b9e6SYuval Mintz return -ENOMEM; 624fe56b9e6SYuval Mintz 625fe56b9e6SYuval Mintz p_igu_info = p_hwfn->hw_info.p_igu_info; 626fe56b9e6SYuval Mintz 627fe56b9e6SYuval Mintz /* Initialize base sb / sb cnt for PFs */ 628fe56b9e6SYuval Mintz p_igu_info->igu_base_sb = 0xffff; 629fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt = 0; 630fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id = 0xffff; 631fe56b9e6SYuval Mintz p_igu_info->igu_base_sb_iov = 0xffff; 632fe56b9e6SYuval Mintz 633fe56b9e6SYuval Mintz for (sb_id = 0; sb_id < QED_MAPPING_MEMORY_SIZE(p_hwfn->cdev); 634fe56b9e6SYuval Mintz sb_id++) { 635fe56b9e6SYuval Mintz blk = &p_igu_info->igu_map.igu_blocks[sb_id]; 636fe56b9e6SYuval Mintz 637fe56b9e6SYuval Mintz val = qed_rd(p_hwfn, p_ptt, 638fe56b9e6SYuval Mintz IGU_REG_MAPPING_MEMORY + sizeof(u32) * sb_id); 639fe56b9e6SYuval Mintz 640fe56b9e6SYuval Mintz /* stop scanning when hit first invalid PF entry */ 641fe56b9e6SYuval Mintz if (!GET_FIELD(val, IGU_MAPPING_LINE_VALID) && 642fe56b9e6SYuval Mintz GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID)) 643fe56b9e6SYuval Mintz break; 644fe56b9e6SYuval Mintz 645fe56b9e6SYuval Mintz blk->status = QED_IGU_STATUS_VALID; 646fe56b9e6SYuval Mintz blk->function_id = GET_FIELD(val, 647fe56b9e6SYuval Mintz IGU_MAPPING_LINE_FUNCTION_NUMBER); 648fe56b9e6SYuval Mintz blk->is_pf = GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID); 649fe56b9e6SYuval Mintz blk->vector_number = GET_FIELD(val, 650fe56b9e6SYuval Mintz IGU_MAPPING_LINE_VECTOR_NUMBER); 651fe56b9e6SYuval Mintz 652fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 653fe56b9e6SYuval Mintz "IGU_BLOCK[sb_id]:%x:func_id = %d is_pf = %d vector_num = 0x%x\n", 654fe56b9e6SYuval Mintz val, blk->function_id, blk->is_pf, 655fe56b9e6SYuval Mintz blk->vector_number); 656fe56b9e6SYuval Mintz 657fe56b9e6SYuval Mintz if (blk->is_pf) { 658fe56b9e6SYuval Mintz if (blk->function_id == p_hwfn->rel_pf_id) { 659fe56b9e6SYuval Mintz blk->status |= QED_IGU_STATUS_PF; 660fe56b9e6SYuval Mintz 661fe56b9e6SYuval Mintz if (blk->vector_number == 0) { 662fe56b9e6SYuval Mintz if (p_igu_info->igu_dsb_id == 0xffff) 663fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id = sb_id; 664fe56b9e6SYuval Mintz } else { 665fe56b9e6SYuval Mintz if (p_igu_info->igu_base_sb == 666fe56b9e6SYuval Mintz 0xffff) { 667fe56b9e6SYuval Mintz p_igu_info->igu_base_sb = sb_id; 668fe56b9e6SYuval Mintz } else if (prev_sb_id != sb_id - 1) { 669fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn->cdev, 670fe56b9e6SYuval Mintz "consecutive igu vectors for HWFN %x broken", 671fe56b9e6SYuval Mintz p_hwfn->rel_pf_id); 672fe56b9e6SYuval Mintz break; 673fe56b9e6SYuval Mintz } 674fe56b9e6SYuval Mintz prev_sb_id = sb_id; 675fe56b9e6SYuval Mintz /* we don't count the default */ 676fe56b9e6SYuval Mintz (p_igu_info->igu_sb_cnt)++; 677fe56b9e6SYuval Mintz } 678fe56b9e6SYuval Mintz } 679fe56b9e6SYuval Mintz } 680fe56b9e6SYuval Mintz } 681fe56b9e6SYuval Mintz 682fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, 683fe56b9e6SYuval Mintz "IGU igu_base_sb=0x%x igu_sb_cnt=%d igu_dsb_id=0x%x\n", 684fe56b9e6SYuval Mintz p_igu_info->igu_base_sb, 685fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt, 686fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id); 687fe56b9e6SYuval Mintz 688fe56b9e6SYuval Mintz if (p_igu_info->igu_base_sb == 0xffff || 689fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id == 0xffff || 690fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt == 0) { 691fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, 692fe56b9e6SYuval Mintz "IGU CAM returned invalid values igu_base_sb=0x%x igu_sb_cnt=%d igu_dsb_id=0x%x\n", 693fe56b9e6SYuval Mintz p_igu_info->igu_base_sb, 694fe56b9e6SYuval Mintz p_igu_info->igu_sb_cnt, 695fe56b9e6SYuval Mintz p_igu_info->igu_dsb_id); 696fe56b9e6SYuval Mintz return -EINVAL; 697fe56b9e6SYuval Mintz } 698fe56b9e6SYuval Mintz 699fe56b9e6SYuval Mintz return 0; 700fe56b9e6SYuval Mintz } 701fe56b9e6SYuval Mintz 702fe56b9e6SYuval Mintz /** 703fe56b9e6SYuval Mintz * @brief Initialize igu runtime registers 704fe56b9e6SYuval Mintz * 705fe56b9e6SYuval Mintz * @param p_hwfn 706fe56b9e6SYuval Mintz */ 707fe56b9e6SYuval Mintz void qed_int_igu_init_rt(struct qed_hwfn *p_hwfn) 708fe56b9e6SYuval Mintz { 709fe56b9e6SYuval Mintz u32 igu_pf_conf = 0; 710fe56b9e6SYuval Mintz 711fe56b9e6SYuval Mintz igu_pf_conf |= IGU_PF_CONF_FUNC_EN; 712fe56b9e6SYuval Mintz 713fe56b9e6SYuval Mintz STORE_RT_REG(p_hwfn, IGU_REG_PF_CONFIGURATION_RT_OFFSET, igu_pf_conf); 714fe56b9e6SYuval Mintz } 715fe56b9e6SYuval Mintz 716fe56b9e6SYuval Mintz u64 qed_int_igu_read_sisr_reg(struct qed_hwfn *p_hwfn) 717fe56b9e6SYuval Mintz { 718fe56b9e6SYuval Mintz u64 intr_status = 0; 719fe56b9e6SYuval Mintz u32 intr_status_lo = 0; 720fe56b9e6SYuval Mintz u32 intr_status_hi = 0; 721fe56b9e6SYuval Mintz u32 lsb_igu_cmd_addr = IGU_REG_SISR_MDPC_WMASK_LSB_UPPER - 722fe56b9e6SYuval Mintz IGU_CMD_INT_ACK_BASE; 723fe56b9e6SYuval Mintz u32 msb_igu_cmd_addr = IGU_REG_SISR_MDPC_WMASK_MSB_UPPER - 724fe56b9e6SYuval Mintz IGU_CMD_INT_ACK_BASE; 725fe56b9e6SYuval Mintz 726fe56b9e6SYuval Mintz intr_status_lo = REG_RD(p_hwfn, 727fe56b9e6SYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 728fe56b9e6SYuval Mintz lsb_igu_cmd_addr * 8); 729fe56b9e6SYuval Mintz intr_status_hi = REG_RD(p_hwfn, 730fe56b9e6SYuval Mintz GTT_BAR0_MAP_REG_IGU_CMD + 731fe56b9e6SYuval Mintz msb_igu_cmd_addr * 8); 732fe56b9e6SYuval Mintz intr_status = ((u64)intr_status_hi << 32) + (u64)intr_status_lo; 733fe56b9e6SYuval Mintz 734fe56b9e6SYuval Mintz return intr_status; 735fe56b9e6SYuval Mintz } 736fe56b9e6SYuval Mintz 737fe56b9e6SYuval Mintz static void qed_int_sp_dpc_setup(struct qed_hwfn *p_hwfn) 738fe56b9e6SYuval Mintz { 739fe56b9e6SYuval Mintz tasklet_init(p_hwfn->sp_dpc, 740fe56b9e6SYuval Mintz qed_int_sp_dpc, (unsigned long)p_hwfn); 741fe56b9e6SYuval Mintz p_hwfn->b_sp_dpc_enabled = true; 742fe56b9e6SYuval Mintz } 743fe56b9e6SYuval Mintz 744fe56b9e6SYuval Mintz static int qed_int_sp_dpc_alloc(struct qed_hwfn *p_hwfn) 745fe56b9e6SYuval Mintz { 746fe56b9e6SYuval Mintz p_hwfn->sp_dpc = kmalloc(sizeof(*p_hwfn->sp_dpc), GFP_ATOMIC); 747fe56b9e6SYuval Mintz if (!p_hwfn->sp_dpc) 748fe56b9e6SYuval Mintz return -ENOMEM; 749fe56b9e6SYuval Mintz 750fe56b9e6SYuval Mintz return 0; 751fe56b9e6SYuval Mintz } 752fe56b9e6SYuval Mintz 753fe56b9e6SYuval Mintz static void qed_int_sp_dpc_free(struct qed_hwfn *p_hwfn) 754fe56b9e6SYuval Mintz { 755fe56b9e6SYuval Mintz kfree(p_hwfn->sp_dpc); 756fe56b9e6SYuval Mintz } 757fe56b9e6SYuval Mintz 758fe56b9e6SYuval Mintz int qed_int_alloc(struct qed_hwfn *p_hwfn, 759fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 760fe56b9e6SYuval Mintz { 761fe56b9e6SYuval Mintz int rc = 0; 762fe56b9e6SYuval Mintz 763fe56b9e6SYuval Mintz rc = qed_int_sp_dpc_alloc(p_hwfn); 764fe56b9e6SYuval Mintz if (rc) { 765fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, "Failed to allocate sp dpc mem\n"); 766fe56b9e6SYuval Mintz return rc; 767fe56b9e6SYuval Mintz } 768fe56b9e6SYuval Mintz rc = qed_int_sp_sb_alloc(p_hwfn, p_ptt); 769fe56b9e6SYuval Mintz if (rc) { 770fe56b9e6SYuval Mintz DP_ERR(p_hwfn->cdev, "Failed to allocate sp sb mem\n"); 771fe56b9e6SYuval Mintz return rc; 772fe56b9e6SYuval Mintz } 773fe56b9e6SYuval Mintz 774fe56b9e6SYuval Mintz return rc; 775fe56b9e6SYuval Mintz } 776fe56b9e6SYuval Mintz 777fe56b9e6SYuval Mintz void qed_int_free(struct qed_hwfn *p_hwfn) 778fe56b9e6SYuval Mintz { 779fe56b9e6SYuval Mintz qed_int_sp_sb_free(p_hwfn); 780fe56b9e6SYuval Mintz qed_int_sp_dpc_free(p_hwfn); 781fe56b9e6SYuval Mintz } 782fe56b9e6SYuval Mintz 783fe56b9e6SYuval Mintz void qed_int_setup(struct qed_hwfn *p_hwfn, 784fe56b9e6SYuval Mintz struct qed_ptt *p_ptt) 785fe56b9e6SYuval Mintz { 786fe56b9e6SYuval Mintz qed_int_sp_sb_setup(p_hwfn, p_ptt); 787fe56b9e6SYuval Mintz qed_int_sp_dpc_setup(p_hwfn); 788fe56b9e6SYuval Mintz } 789fe56b9e6SYuval Mintz 790fe56b9e6SYuval Mintz int qed_int_get_num_sbs(struct qed_hwfn *p_hwfn, 791fe56b9e6SYuval Mintz int *p_iov_blks) 792fe56b9e6SYuval Mintz { 793fe56b9e6SYuval Mintz struct qed_igu_info *info = p_hwfn->hw_info.p_igu_info; 794fe56b9e6SYuval Mintz 795fe56b9e6SYuval Mintz if (!info) 796fe56b9e6SYuval Mintz return 0; 797fe56b9e6SYuval Mintz 798fe56b9e6SYuval Mintz if (p_iov_blks) 799fe56b9e6SYuval Mintz *p_iov_blks = info->free_blks; 800fe56b9e6SYuval Mintz 801fe56b9e6SYuval Mintz return info->igu_sb_cnt; 802fe56b9e6SYuval Mintz } 803