1*52fa7bf9SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 27725ccfdSJing Huang /* 3889d0d42SAnil Gurumurthy * Copyright (c) 2005-2014 Brocade Communications Systems, Inc. 4889d0d42SAnil Gurumurthy * Copyright (c) 2014- QLogic Corporation. 57725ccfdSJing Huang * All rights reserved 6889d0d42SAnil Gurumurthy * www.qlogic.com 77725ccfdSJing Huang * 831e1d569SAnil Gurumurthy * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter. 97725ccfdSJing Huang */ 107725ccfdSJing Huang 11f16a1750SMaggie Zhang #include "bfad_drv.h" 12a36c61f9SKrishna Gudipati #include "bfa_modules.h" 1311189208SKrishna Gudipati #include "bfi_reg.h" 147725ccfdSJing Huang 157725ccfdSJing Huang void 167725ccfdSJing Huang bfa_hwcb_reginit(struct bfa_s *bfa) 177725ccfdSJing Huang { 187725ccfdSJing Huang struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs; 1953440260SJing Huang void __iomem *kva = bfa_ioc_bar0(&bfa->ioc); 2011189208SKrishna Gudipati int fn = bfa_ioc_pcifn(&bfa->ioc); 217725ccfdSJing Huang 227725ccfdSJing Huang if (fn == 0) { 237725ccfdSJing Huang bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS); 247725ccfdSJing Huang bfa_regs->intr_mask = (kva + HOSTFN0_INT_MSK); 257725ccfdSJing Huang } else { 267725ccfdSJing Huang bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS); 277725ccfdSJing Huang bfa_regs->intr_mask = (kva + HOSTFN1_INT_MSK); 287725ccfdSJing Huang } 297725ccfdSJing Huang } 307725ccfdSJing Huang 31f5713c5dSKrishna Gudipati static void 32f5713c5dSKrishna Gudipati bfa_hwcb_reqq_ack_msix(struct bfa_s *bfa, int reqq) 33f5713c5dSKrishna Gudipati { 3453440260SJing Huang writel(__HFN_INT_CPE_Q0 << CPE_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), reqq), 3553440260SJing Huang bfa->iocfc.bfa_regs.intr_status); 36f5713c5dSKrishna Gudipati } 37f5713c5dSKrishna Gudipati 38ca6e0ea7SKrishna Gudipati /* 39ca6e0ea7SKrishna Gudipati * Actions to respond RME Interrupt for Crossbow ASIC: 40ca6e0ea7SKrishna Gudipati * - Write 1 to Interrupt Status register 41ca6e0ea7SKrishna Gudipati * INTX - done in bfa_intx() 42ca6e0ea7SKrishna Gudipati * MSIX - done in bfa_hwcb_rspq_ack_msix() 43ca6e0ea7SKrishna Gudipati * - Update CI (only if new CI) 44ca6e0ea7SKrishna Gudipati */ 457725ccfdSJing Huang static void 46ca6e0ea7SKrishna Gudipati bfa_hwcb_rspq_ack_msix(struct bfa_s *bfa, int rspq, u32 ci) 477725ccfdSJing Huang { 4853440260SJing Huang writel(__HFN_INT_RME_Q0 << RME_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), rspq), 4953440260SJing Huang bfa->iocfc.bfa_regs.intr_status); 50ca6e0ea7SKrishna Gudipati 51ca6e0ea7SKrishna Gudipati if (bfa_rspq_ci(bfa, rspq) == ci) 52ca6e0ea7SKrishna Gudipati return; 53ca6e0ea7SKrishna Gudipati 54ca6e0ea7SKrishna Gudipati bfa_rspq_ci(bfa, rspq) = ci; 55ca6e0ea7SKrishna Gudipati writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]); 56ca6e0ea7SKrishna Gudipati } 57ca6e0ea7SKrishna Gudipati 58ca6e0ea7SKrishna Gudipati void 59ca6e0ea7SKrishna Gudipati bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci) 60ca6e0ea7SKrishna Gudipati { 61ca6e0ea7SKrishna Gudipati if (bfa_rspq_ci(bfa, rspq) == ci) 62ca6e0ea7SKrishna Gudipati return; 63ca6e0ea7SKrishna Gudipati 64ca6e0ea7SKrishna Gudipati bfa_rspq_ci(bfa, rspq) = ci; 65ca6e0ea7SKrishna Gudipati writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]); 667725ccfdSJing Huang } 677725ccfdSJing Huang 687725ccfdSJing Huang void 697725ccfdSJing Huang bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap, 707725ccfdSJing Huang u32 *num_vecs, u32 *max_vec_bit) 717725ccfdSJing Huang { 727725ccfdSJing Huang #define __HFN_NUMINTS 13 737725ccfdSJing Huang if (bfa_ioc_pcifn(&bfa->ioc) == 0) { 747725ccfdSJing Huang *msix_vecs_bmap = (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 | 757725ccfdSJing Huang __HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 | 767725ccfdSJing Huang __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 | 777725ccfdSJing Huang __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 | 787725ccfdSJing Huang __HFN_INT_MBOX_LPU0); 797725ccfdSJing Huang *max_vec_bit = __HFN_INT_MBOX_LPU0; 807725ccfdSJing Huang } else { 817725ccfdSJing Huang *msix_vecs_bmap = (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 | 827725ccfdSJing Huang __HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 | 837725ccfdSJing Huang __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 | 847725ccfdSJing Huang __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 | 857725ccfdSJing Huang __HFN_INT_MBOX_LPU1); 867725ccfdSJing Huang *max_vec_bit = __HFN_INT_MBOX_LPU1; 877725ccfdSJing Huang } 887725ccfdSJing Huang 897725ccfdSJing Huang *msix_vecs_bmap |= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 | 907725ccfdSJing Huang __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS); 917725ccfdSJing Huang *num_vecs = __HFN_NUMINTS; 927725ccfdSJing Huang } 937725ccfdSJing Huang 945fbe25c7SJing Huang /* 95775c7742SKrishna Gudipati * Dummy interrupt handler for handling spurious interrupts. 96775c7742SKrishna Gudipati */ 97775c7742SKrishna Gudipati static void 98775c7742SKrishna Gudipati bfa_hwcb_msix_dummy(struct bfa_s *bfa, int vec) 99775c7742SKrishna Gudipati { 100775c7742SKrishna Gudipati } 101775c7742SKrishna Gudipati 102775c7742SKrishna Gudipati /* 1037725ccfdSJing Huang * No special setup required for crossbow -- vector assignments are implicit. 1047725ccfdSJing Huang */ 1057725ccfdSJing Huang void 1067725ccfdSJing Huang bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs) 1077725ccfdSJing Huang { 108d4b671c5SJing Huang WARN_ON((nvecs != 1) && (nvecs != __HFN_NUMINTS)); 1097725ccfdSJing Huang 1107725ccfdSJing Huang bfa->msix.nvecs = nvecs; 111775c7742SKrishna Gudipati bfa_hwcb_msix_uninstall(bfa); 112775c7742SKrishna Gudipati } 113775c7742SKrishna Gudipati 114775c7742SKrishna Gudipati void 115775c7742SKrishna Gudipati bfa_hwcb_msix_ctrl_install(struct bfa_s *bfa) 116775c7742SKrishna Gudipati { 117775c7742SKrishna Gudipati int i; 118775c7742SKrishna Gudipati 119775c7742SKrishna Gudipati if (bfa->msix.nvecs == 0) 120775c7742SKrishna Gudipati return; 121775c7742SKrishna Gudipati 122775c7742SKrishna Gudipati if (bfa->msix.nvecs == 1) { 12310a07379SKrishna Gudipati for (i = BFI_MSIX_CPE_QMIN_CB; i < BFI_MSIX_CB_MAX; i++) 124775c7742SKrishna Gudipati bfa->msix.handler[i] = bfa_msix_all; 125775c7742SKrishna Gudipati return; 126775c7742SKrishna Gudipati } 127775c7742SKrishna Gudipati 128775c7742SKrishna Gudipati for (i = BFI_MSIX_RME_QMAX_CB+1; i < BFI_MSIX_CB_MAX; i++) 129775c7742SKrishna Gudipati bfa->msix.handler[i] = bfa_msix_lpu_err; 130775c7742SKrishna Gudipati } 131775c7742SKrishna Gudipati 132775c7742SKrishna Gudipati void 133775c7742SKrishna Gudipati bfa_hwcb_msix_queue_install(struct bfa_s *bfa) 134775c7742SKrishna Gudipati { 135775c7742SKrishna Gudipati int i; 136775c7742SKrishna Gudipati 137775c7742SKrishna Gudipati if (bfa->msix.nvecs == 0) 138775c7742SKrishna Gudipati return; 139775c7742SKrishna Gudipati 140775c7742SKrishna Gudipati if (bfa->msix.nvecs == 1) { 141775c7742SKrishna Gudipati for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++) 1427725ccfdSJing Huang bfa->msix.handler[i] = bfa_msix_all; 1437725ccfdSJing Huang return; 1447725ccfdSJing Huang } 1457725ccfdSJing Huang 14611189208SKrishna Gudipati for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_CPE_QMAX_CB; i++) 1477725ccfdSJing Huang bfa->msix.handler[i] = bfa_msix_reqq; 1487725ccfdSJing Huang 14911189208SKrishna Gudipati for (i = BFI_MSIX_RME_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++) 1507725ccfdSJing Huang bfa->msix.handler[i] = bfa_msix_rspq; 1517725ccfdSJing Huang } 1527725ccfdSJing Huang 1537725ccfdSJing Huang void 1547725ccfdSJing Huang bfa_hwcb_msix_uninstall(struct bfa_s *bfa) 1557725ccfdSJing Huang { 156775c7742SKrishna Gudipati int i; 157775c7742SKrishna Gudipati 158775c7742SKrishna Gudipati for (i = 0; i < BFI_MSIX_CB_MAX; i++) 159775c7742SKrishna Gudipati bfa->msix.handler[i] = bfa_hwcb_msix_dummy; 1607725ccfdSJing Huang } 1617725ccfdSJing Huang 1625fbe25c7SJing Huang /* 1637725ccfdSJing Huang * No special enable/disable -- vector assignments are implicit. 1647725ccfdSJing Huang */ 1657725ccfdSJing Huang void 1667725ccfdSJing Huang bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix) 1677725ccfdSJing Huang { 168ca6e0ea7SKrishna Gudipati if (msix) { 169f5713c5dSKrishna Gudipati bfa->iocfc.hwif.hw_reqq_ack = bfa_hwcb_reqq_ack_msix; 1707725ccfdSJing Huang bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix; 171ca6e0ea7SKrishna Gudipati } else { 172ca6e0ea7SKrishna Gudipati bfa->iocfc.hwif.hw_reqq_ack = NULL; 173ca6e0ea7SKrishna Gudipati bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack; 174ca6e0ea7SKrishna Gudipati } 1757725ccfdSJing Huang } 1767725ccfdSJing Huang 17736d345a7SJing Huang void 17836d345a7SJing Huang bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end) 17936d345a7SJing Huang { 18011189208SKrishna Gudipati *start = BFI_MSIX_RME_QMIN_CB; 18111189208SKrishna Gudipati *end = BFI_MSIX_RME_QMAX_CB; 18236d345a7SJing Huang } 183