1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (c) 2005-2014 Brocade Communications Systems, Inc. |
4 | * Copyright (c) 2014- QLogic Corporation. |
5 | * All rights reserved |
6 | * www.qlogic.com |
7 | * |
8 | * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter. |
9 | */ |
10 | |
11 | #include "bfad_drv.h" |
12 | #include "bfa_modules.h" |
13 | #include "bfi_reg.h" |
14 | |
15 | BFA_TRC_FILE(HAL, IOCFC_CT); |
16 | |
17 | /* |
18 | * Dummy interrupt handler for handling spurious interrupt during chip-reinit. |
19 | */ |
20 | static void |
21 | bfa_hwct_msix_dummy(struct bfa_s *bfa, int vec) |
22 | { |
23 | } |
24 | |
25 | void |
26 | bfa_hwct_reginit(struct bfa_s *bfa) |
27 | { |
28 | struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs; |
29 | void __iomem *kva = bfa_ioc_bar0(&bfa->ioc); |
30 | int fn = bfa_ioc_pcifn(&bfa->ioc); |
31 | |
32 | if (fn == 0) { |
33 | bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS); |
34 | bfa_regs->intr_mask = (kva + HOSTFN0_INT_MSK); |
35 | } else { |
36 | bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS); |
37 | bfa_regs->intr_mask = (kva + HOSTFN1_INT_MSK); |
38 | } |
39 | } |
40 | |
41 | void |
42 | bfa_hwct2_reginit(struct bfa_s *bfa) |
43 | { |
44 | struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs; |
45 | void __iomem *kva = bfa_ioc_bar0(&bfa->ioc); |
46 | |
47 | bfa_regs->intr_status = (kva + CT2_HOSTFN_INT_STATUS); |
48 | bfa_regs->intr_mask = (kva + CT2_HOSTFN_INTR_MASK); |
49 | } |
50 | |
51 | void |
52 | bfa_hwct_reqq_ack(struct bfa_s *bfa, int reqq) |
53 | { |
54 | u32 r32; |
55 | |
56 | r32 = readl(addr: bfa->iocfc.bfa_regs.cpe_q_ctrl[reqq]); |
57 | writel(val: r32, addr: bfa->iocfc.bfa_regs.cpe_q_ctrl[reqq]); |
58 | } |
59 | |
60 | /* |
61 | * Actions to respond RME Interrupt for Catapult ASIC: |
62 | * - Write 1 to Interrupt Status register (INTx only - done in bfa_intx()) |
63 | * - Acknowledge by writing to RME Queue Control register |
64 | * - Update CI |
65 | */ |
66 | void |
67 | bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci) |
68 | { |
69 | u32 r32; |
70 | |
71 | r32 = readl(addr: bfa->iocfc.bfa_regs.rme_q_ctrl[rspq]); |
72 | writel(val: r32, addr: bfa->iocfc.bfa_regs.rme_q_ctrl[rspq]); |
73 | |
74 | bfa_rspq_ci(bfa, rspq) = ci; |
75 | writel(val: ci, addr: bfa->iocfc.bfa_regs.rme_q_ci[rspq]); |
76 | } |
77 | |
78 | /* |
79 | * Actions to respond RME Interrupt for Catapult2 ASIC: |
80 | * - Write 1 to Interrupt Status register (INTx only - done in bfa_intx()) |
81 | * - Update CI |
82 | */ |
83 | void |
84 | bfa_hwct2_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci) |
85 | { |
86 | bfa_rspq_ci(bfa, rspq) = ci; |
87 | writel(val: ci, addr: bfa->iocfc.bfa_regs.rme_q_ci[rspq]); |
88 | } |
89 | |
90 | void |
91 | bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap, |
92 | u32 *num_vecs, u32 *max_vec_bit) |
93 | { |
94 | *msix_vecs_bmap = (1 << BFI_MSIX_CT_MAX) - 1; |
95 | *max_vec_bit = (1 << (BFI_MSIX_CT_MAX - 1)); |
96 | *num_vecs = BFI_MSIX_CT_MAX; |
97 | } |
98 | |
99 | /* |
100 | * Setup MSI-X vector for catapult |
101 | */ |
102 | void |
103 | bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs) |
104 | { |
105 | WARN_ON((nvecs != 1) && (nvecs != BFI_MSIX_CT_MAX)); |
106 | bfa_trc(bfa, nvecs); |
107 | |
108 | bfa->msix.nvecs = nvecs; |
109 | bfa_hwct_msix_uninstall(bfa); |
110 | } |
111 | |
112 | void |
113 | bfa_hwct_msix_ctrl_install(struct bfa_s *bfa) |
114 | { |
115 | if (bfa->msix.nvecs == 0) |
116 | return; |
117 | |
118 | if (bfa->msix.nvecs == 1) |
119 | bfa->msix.handler[BFI_MSIX_LPU_ERR_CT] = bfa_msix_all; |
120 | else |
121 | bfa->msix.handler[BFI_MSIX_LPU_ERR_CT] = bfa_msix_lpu_err; |
122 | } |
123 | |
124 | void |
125 | bfa_hwct_msix_queue_install(struct bfa_s *bfa) |
126 | { |
127 | int i; |
128 | |
129 | if (bfa->msix.nvecs == 0) |
130 | return; |
131 | |
132 | if (bfa->msix.nvecs == 1) { |
133 | for (i = BFI_MSIX_CPE_QMIN_CT; i < BFI_MSIX_CT_MAX; i++) |
134 | bfa->msix.handler[i] = bfa_msix_all; |
135 | return; |
136 | } |
137 | |
138 | for (i = BFI_MSIX_CPE_QMIN_CT; i <= BFI_MSIX_CPE_QMAX_CT; i++) |
139 | bfa->msix.handler[i] = bfa_msix_reqq; |
140 | |
141 | for (i = BFI_MSIX_RME_QMIN_CT; i <= BFI_MSIX_RME_QMAX_CT; i++) |
142 | bfa->msix.handler[i] = bfa_msix_rspq; |
143 | } |
144 | |
145 | void |
146 | bfa_hwct_msix_uninstall(struct bfa_s *bfa) |
147 | { |
148 | int i; |
149 | |
150 | for (i = 0; i < BFI_MSIX_CT_MAX; i++) |
151 | bfa->msix.handler[i] = bfa_hwct_msix_dummy; |
152 | } |
153 | |
154 | /* |
155 | * Enable MSI-X vectors |
156 | */ |
157 | void |
158 | bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix) |
159 | { |
160 | bfa_trc(bfa, 0); |
161 | bfa_ioc_isr_mode_set(&bfa->ioc, msix); |
162 | } |
163 | |
164 | void |
165 | bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end) |
166 | { |
167 | *start = BFI_MSIX_RME_QMIN_CT; |
168 | *end = BFI_MSIX_RME_QMAX_CT; |
169 | } |
170 | |