2d1e535c46274ea7643c840a35fc292944bde057
[dpdk.git] / drivers / common / cnxk / roc_npa_irq.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4
5 #include "roc_api.h"
6 #include "roc_priv.h"
7
8 static void
9 npa_err_irq(void *param)
10 {
11         struct npa_lf *lf = (struct npa_lf *)param;
12         uint64_t intr;
13
14         intr = plt_read64(lf->base + NPA_LF_ERR_INT);
15         if (intr == 0)
16                 return;
17
18         plt_err("Err_intr=0x%" PRIx64 "", intr);
19
20         /* Clear interrupt */
21         plt_write64(intr, lf->base + NPA_LF_ERR_INT);
22 }
23
24 static int
25 npa_register_err_irq(struct npa_lf *lf)
26 {
27         struct plt_intr_handle *handle = lf->intr_handle;
28         int rc, vec;
29
30         vec = lf->npa_msixoff + NPA_LF_INT_VEC_ERR_INT;
31
32         /* Clear err interrupt */
33         plt_write64(~0ull, lf->base + NPA_LF_ERR_INT_ENA_W1C);
34         /* Register err interrupt vector */
35         rc = dev_irq_register(handle, npa_err_irq, lf, vec);
36
37         /* Enable hw interrupt */
38         plt_write64(~0ull, lf->base + NPA_LF_ERR_INT_ENA_W1S);
39
40         return rc;
41 }
42
43 static void
44 npa_unregister_err_irq(struct npa_lf *lf)
45 {
46         struct plt_intr_handle *handle = lf->intr_handle;
47         int vec;
48
49         vec = lf->npa_msixoff + NPA_LF_INT_VEC_ERR_INT;
50
51         /* Clear err interrupt */
52         plt_write64(~0ull, lf->base + NPA_LF_ERR_INT_ENA_W1C);
53         dev_irq_unregister(handle, npa_err_irq, lf, vec);
54 }
55
56 static void
57 npa_ras_irq(void *param)
58 {
59         struct npa_lf *lf = (struct npa_lf *)param;
60         uint64_t intr;
61
62         intr = plt_read64(lf->base + NPA_LF_RAS);
63         if (intr == 0)
64                 return;
65
66         plt_err("Ras_intr=0x%" PRIx64 "", intr);
67
68         /* Clear interrupt */
69         plt_write64(intr, lf->base + NPA_LF_RAS);
70 }
71
72 static int
73 npa_register_ras_irq(struct npa_lf *lf)
74 {
75         struct plt_intr_handle *handle = lf->intr_handle;
76         int rc, vec;
77
78         vec = lf->npa_msixoff + NPA_LF_INT_VEC_POISON;
79
80         /* Clear err interrupt */
81         plt_write64(~0ull, lf->base + NPA_LF_RAS_ENA_W1C);
82         /* Set used interrupt vectors */
83         rc = dev_irq_register(handle, npa_ras_irq, lf, vec);
84         /* Enable hw interrupt */
85         plt_write64(~0ull, lf->base + NPA_LF_RAS_ENA_W1S);
86
87         return rc;
88 }
89
90 static void
91 npa_unregister_ras_irq(struct npa_lf *lf)
92 {
93         int vec;
94         struct plt_intr_handle *handle = lf->intr_handle;
95
96         vec = lf->npa_msixoff + NPA_LF_INT_VEC_POISON;
97
98         /* Clear err interrupt */
99         plt_write64(~0ull, lf->base + NPA_LF_RAS_ENA_W1C);
100         dev_irq_unregister(handle, npa_ras_irq, lf, vec);
101 }
102
103 static inline uint8_t
104 npa_q_irq_get_and_clear(struct npa_lf *lf, uint32_t q, uint32_t off,
105                         uint64_t mask)
106 {
107         uint64_t reg, wdata;
108         uint8_t qint;
109
110         wdata = (uint64_t)q << 44;
111         reg = roc_atomic64_add_nosync(wdata, (int64_t *)(lf->base + off));
112
113         if (reg & BIT_ULL(42) /* OP_ERR */) {
114                 plt_err("Failed execute irq get off=0x%x", off);
115                 return 0;
116         }
117
118         qint = reg & 0xff;
119         wdata &= mask;
120         plt_write64(wdata | qint, lf->base + off);
121
122         return qint;
123 }
124
125 static inline uint8_t
126 npa_pool_irq_get_and_clear(struct npa_lf *lf, uint32_t p)
127 {
128         return npa_q_irq_get_and_clear(lf, p, NPA_LF_POOL_OP_INT, ~0xff00);
129 }
130
131 static inline uint8_t
132 npa_aura_irq_get_and_clear(struct npa_lf *lf, uint32_t a)
133 {
134         return npa_q_irq_get_and_clear(lf, a, NPA_LF_AURA_OP_INT, ~0xff00);
135 }
136
137 static void
138 npa_q_irq(void *param)
139 {
140         struct npa_qint *qint = (struct npa_qint *)param;
141         struct npa_lf *lf = qint->lf;
142         uint8_t irq, qintx = qint->qintx;
143         uint32_t q, pool, aura;
144         uint64_t intr;
145
146         intr = plt_read64(lf->base + NPA_LF_QINTX_INT(qintx));
147         if (intr == 0)
148                 return;
149
150         plt_err("queue_intr=0x%" PRIx64 " qintx=%d", intr, qintx);
151
152         /* Handle pool queue interrupts */
153         for (q = 0; q < lf->nr_pools; q++) {
154                 /* Skip disabled POOL */
155                 if (plt_bitmap_get(lf->npa_bmp, q))
156                         continue;
157
158                 pool = q % lf->qints;
159                 irq = npa_pool_irq_get_and_clear(lf, pool);
160
161                 if (irq & BIT_ULL(NPA_POOL_ERR_INT_OVFLS))
162                         plt_err("Pool=%d NPA_POOL_ERR_INT_OVFLS", pool);
163
164                 if (irq & BIT_ULL(NPA_POOL_ERR_INT_RANGE))
165                         plt_err("Pool=%d NPA_POOL_ERR_INT_RANGE", pool);
166
167                 if (irq & BIT_ULL(NPA_POOL_ERR_INT_PERR))
168                         plt_err("Pool=%d NPA_POOL_ERR_INT_PERR", pool);
169         }
170
171         /* Handle aura queue interrupts */
172         for (q = 0; q < lf->nr_pools; q++) {
173                 /* Skip disabled AURA */
174                 if (plt_bitmap_get(lf->npa_bmp, q))
175                         continue;
176
177                 aura = q % lf->qints;
178                 irq = npa_aura_irq_get_and_clear(lf, aura);
179
180                 if (irq & BIT_ULL(NPA_AURA_ERR_INT_AURA_ADD_OVER))
181                         plt_err("Aura=%d NPA_AURA_ERR_INT_ADD_OVER", aura);
182
183                 if (irq & BIT_ULL(NPA_AURA_ERR_INT_AURA_ADD_UNDER))
184                         plt_err("Aura=%d NPA_AURA_ERR_INT_ADD_UNDER", aura);
185
186                 if (irq & BIT_ULL(NPA_AURA_ERR_INT_AURA_FREE_UNDER))
187                         plt_err("Aura=%d NPA_AURA_ERR_INT_FREE_UNDER", aura);
188
189                 if (irq & BIT_ULL(NPA_AURA_ERR_INT_POOL_DIS))
190                         plt_err("Aura=%d NPA_AURA_ERR_POOL_DIS", aura);
191         }
192
193         /* Clear interrupt */
194         plt_write64(intr, lf->base + NPA_LF_QINTX_INT(qintx));
195 }
196
197 static int
198 npa_register_queue_irqs(struct npa_lf *lf)
199 {
200         struct plt_intr_handle *handle = lf->intr_handle;
201         int vec, q, qs, rc = 0;
202
203         /* Figure out max qintx required */
204         qs = PLT_MIN(lf->qints, lf->nr_pools);
205
206         for (q = 0; q < qs; q++) {
207                 vec = lf->npa_msixoff + NPA_LF_INT_VEC_QINT_START + q;
208
209                 /* Clear QINT CNT */
210                 plt_write64(0, lf->base + NPA_LF_QINTX_CNT(q));
211
212                 /* Clear interrupt */
213                 plt_write64(~0ull, lf->base + NPA_LF_QINTX_ENA_W1C(q));
214
215                 struct npa_qint *qintmem = lf->npa_qint_mem;
216
217                 qintmem += q;
218
219                 qintmem->lf = lf;
220                 qintmem->qintx = q;
221
222                 /* Sync qints_mem update */
223                 plt_wmb();
224
225                 /* Register queue irq vector */
226                 rc = dev_irq_register(handle, npa_q_irq, qintmem, vec);
227                 if (rc)
228                         break;
229
230                 plt_write64(0, lf->base + NPA_LF_QINTX_CNT(q));
231                 plt_write64(0, lf->base + NPA_LF_QINTX_INT(q));
232                 /* Enable QINT interrupt */
233                 plt_write64(~0ull, lf->base + NPA_LF_QINTX_ENA_W1S(q));
234         }
235
236         return rc;
237 }
238
239 static void
240 npa_unregister_queue_irqs(struct npa_lf *lf)
241 {
242         struct plt_intr_handle *handle = lf->intr_handle;
243         int vec, q, qs;
244
245         /* Figure out max qintx required */
246         qs = PLT_MIN(lf->qints, lf->nr_pools);
247
248         for (q = 0; q < qs; q++) {
249                 vec = lf->npa_msixoff + NPA_LF_INT_VEC_QINT_START + q;
250
251                 /* Clear QINT CNT */
252                 plt_write64(0, lf->base + NPA_LF_QINTX_CNT(q));
253                 plt_write64(0, lf->base + NPA_LF_QINTX_INT(q));
254
255                 /* Clear interrupt */
256                 plt_write64(~0ull, lf->base + NPA_LF_QINTX_ENA_W1C(q));
257
258                 struct npa_qint *qintmem = lf->npa_qint_mem;
259
260                 qintmem += q;
261
262                 /* Unregister queue irq vector */
263                 dev_irq_unregister(handle, npa_q_irq, qintmem, vec);
264
265                 qintmem->lf = NULL;
266                 qintmem->qintx = 0;
267         }
268 }
269
270 int
271 npa_register_irqs(struct npa_lf *lf)
272 {
273         int rc;
274
275         if (lf->npa_msixoff == MSIX_VECTOR_INVALID) {
276                 plt_err("Invalid NPALF MSIX vector offset vector: 0x%x",
277                         lf->npa_msixoff);
278                 return NPA_ERR_PARAM;
279         }
280
281         /* Register lf err interrupt */
282         rc = npa_register_err_irq(lf);
283         /* Register RAS interrupt */
284         rc |= npa_register_ras_irq(lf);
285         /* Register queue interrupts */
286         rc |= npa_register_queue_irqs(lf);
287
288         return rc;
289 }
290
291 void
292 npa_unregister_irqs(struct npa_lf *lf)
293 {
294         npa_unregister_err_irq(lf);
295         npa_unregister_ras_irq(lf);
296         npa_unregister_queue_irqs(lf);
297 }