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