1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (C) 2019 Marvell International Ltd.
3 */
4 #include <rte_cryptodev.h>
5
6 #include "otx2_common.h"
7 #include "otx2_cryptodev.h"
8 #include "otx2_cryptodev_hw_access.h"
9 #include "otx2_cryptodev_mbox.h"
10 #include "otx2_cryptodev_ops.h"
11 #include "otx2_dev.h"
12
13 #include "cpt_pmd_logs.h"
14
15 static void
otx2_cpt_lf_err_intr_handler(void * param)16 otx2_cpt_lf_err_intr_handler(void *param)
17 {
18 uintptr_t base = (uintptr_t)param;
19 uint8_t lf_id;
20 uint64_t intr;
21
22 lf_id = (base >> 12) & 0xFF;
23
24 intr = otx2_read64(base + OTX2_CPT_LF_MISC_INT);
25 if (intr == 0)
26 return;
27
28 CPT_LOG_ERR("LF %d MISC_INT: 0x%" PRIx64 "", lf_id, intr);
29
30 /* Clear interrupt */
31 otx2_write64(intr, base + OTX2_CPT_LF_MISC_INT);
32 }
33
34 static void
otx2_cpt_lf_err_intr_unregister(const struct rte_cryptodev * dev,uint16_t msix_off,uintptr_t base)35 otx2_cpt_lf_err_intr_unregister(const struct rte_cryptodev *dev,
36 uint16_t msix_off, uintptr_t base)
37 {
38 struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev->device);
39 struct rte_intr_handle *handle = &pci_dev->intr_handle;
40
41 /* Disable error interrupts */
42 otx2_write64(~0ull, base + OTX2_CPT_LF_MISC_INT_ENA_W1C);
43
44 otx2_unregister_irq(handle, otx2_cpt_lf_err_intr_handler, (void *)base,
45 msix_off);
46 }
47
48 void
otx2_cpt_err_intr_unregister(const struct rte_cryptodev * dev)49 otx2_cpt_err_intr_unregister(const struct rte_cryptodev *dev)
50 {
51 struct otx2_cpt_vf *vf = dev->data->dev_private;
52 uintptr_t base;
53 uint32_t i;
54
55 for (i = 0; i < vf->nb_queues; i++) {
56 base = OTX2_CPT_LF_BAR2(vf, i);
57 otx2_cpt_lf_err_intr_unregister(dev, vf->lf_msixoff[i], base);
58 }
59
60 vf->err_intr_registered = 0;
61 }
62
63 static int
otx2_cpt_lf_err_intr_register(const struct rte_cryptodev * dev,uint16_t msix_off,uintptr_t base)64 otx2_cpt_lf_err_intr_register(const struct rte_cryptodev *dev,
65 uint16_t msix_off, uintptr_t base)
66 {
67 struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev->device);
68 struct rte_intr_handle *handle = &pci_dev->intr_handle;
69 int ret;
70
71 /* Disable error interrupts */
72 otx2_write64(~0ull, base + OTX2_CPT_LF_MISC_INT_ENA_W1C);
73
74 /* Register error interrupt handler */
75 ret = otx2_register_irq(handle, otx2_cpt_lf_err_intr_handler,
76 (void *)base, msix_off);
77 if (ret)
78 return ret;
79
80 /* Enable error interrupts */
81 otx2_write64(~0ull, base + OTX2_CPT_LF_MISC_INT_ENA_W1S);
82
83 return 0;
84 }
85
86 int
otx2_cpt_err_intr_register(const struct rte_cryptodev * dev)87 otx2_cpt_err_intr_register(const struct rte_cryptodev *dev)
88 {
89 struct otx2_cpt_vf *vf = dev->data->dev_private;
90 uint32_t i, j, ret;
91 uintptr_t base;
92
93 for (i = 0; i < vf->nb_queues; i++) {
94 if (vf->lf_msixoff[i] == MSIX_VECTOR_INVALID) {
95 CPT_LOG_ERR("Invalid CPT LF MSI-X offset: 0x%x",
96 vf->lf_msixoff[i]);
97 return -EINVAL;
98 }
99 }
100
101 for (i = 0; i < vf->nb_queues; i++) {
102 base = OTX2_CPT_LF_BAR2(vf, i);
103 ret = otx2_cpt_lf_err_intr_register(dev, vf->lf_msixoff[i],
104 base);
105 if (ret)
106 goto intr_unregister;
107 }
108
109 vf->err_intr_registered = 1;
110 return 0;
111
112 intr_unregister:
113 /* Unregister the ones already registered */
114 for (j = 0; j < i; j++) {
115 base = OTX2_CPT_LF_BAR2(vf, j);
116 otx2_cpt_lf_err_intr_unregister(dev, vf->lf_msixoff[j], base);
117 }
118
119 /*
120 * Failed to register error interrupt. Not returning error as this would
121 * prevent application from enabling larger number of devs.
122 *
123 * This failure is a known issue because otx2_dev_init() initializes
124 * interrupts based on static values from ATF, and the actual number
125 * of interrupts needed (which is based on LFs) can be determined only
126 * after otx2_dev_init() sets up interrupts which includes mbox
127 * interrupts.
128 */
129 return 0;
130 }
131
132 int
otx2_cpt_iq_enable(const struct rte_cryptodev * dev,const struct otx2_cpt_qp * qp,uint8_t grp_mask,uint8_t pri,uint32_t size_div40)133 otx2_cpt_iq_enable(const struct rte_cryptodev *dev,
134 const struct otx2_cpt_qp *qp, uint8_t grp_mask, uint8_t pri,
135 uint32_t size_div40)
136 {
137 union otx2_cpt_af_lf_ctl af_lf_ctl;
138 union otx2_cpt_lf_inprog inprog;
139 union otx2_cpt_lf_q_base base;
140 union otx2_cpt_lf_q_size size;
141 union otx2_cpt_lf_ctl lf_ctl;
142 int ret;
143
144 /* Set engine group mask and priority */
145
146 ret = otx2_cpt_af_reg_read(dev, OTX2_CPT_AF_LF_CTL(qp->id),
147 &af_lf_ctl.u);
148 if (ret)
149 return ret;
150 af_lf_ctl.s.grp = grp_mask;
151 af_lf_ctl.s.pri = pri ? 1 : 0;
152 ret = otx2_cpt_af_reg_write(dev, OTX2_CPT_AF_LF_CTL(qp->id),
153 af_lf_ctl.u);
154 if (ret)
155 return ret;
156
157 /* Set instruction queue base address */
158
159 base.u = otx2_read64(qp->base + OTX2_CPT_LF_Q_BASE);
160 base.s.fault = 0;
161 base.s.stopped = 0;
162 base.s.addr = qp->iq_dma_addr >> 7;
163 otx2_write64(base.u, qp->base + OTX2_CPT_LF_Q_BASE);
164
165 /* Set instruction queue size */
166
167 size.u = otx2_read64(qp->base + OTX2_CPT_LF_Q_SIZE);
168 size.s.size_div40 = size_div40;
169 otx2_write64(size.u, qp->base + OTX2_CPT_LF_Q_SIZE);
170
171 /* Enable instruction queue */
172
173 lf_ctl.u = otx2_read64(qp->base + OTX2_CPT_LF_CTL);
174 lf_ctl.s.ena = 1;
175 otx2_write64(lf_ctl.u, qp->base + OTX2_CPT_LF_CTL);
176
177 /* Start instruction execution */
178
179 inprog.u = otx2_read64(qp->base + OTX2_CPT_LF_INPROG);
180 inprog.s.eena = 1;
181 otx2_write64(inprog.u, qp->base + OTX2_CPT_LF_INPROG);
182
183 return 0;
184 }
185
186 void
otx2_cpt_iq_disable(struct otx2_cpt_qp * qp)187 otx2_cpt_iq_disable(struct otx2_cpt_qp *qp)
188 {
189 union otx2_cpt_lf_q_grp_ptr grp_ptr;
190 union otx2_cpt_lf_inprog inprog;
191 union otx2_cpt_lf_ctl ctl;
192 int cnt;
193
194 /* Stop instruction execution */
195 inprog.u = otx2_read64(qp->base + OTX2_CPT_LF_INPROG);
196 inprog.s.eena = 0x0;
197 otx2_write64(inprog.u, qp->base + OTX2_CPT_LF_INPROG);
198
199 /* Disable instructions enqueuing */
200 ctl.u = otx2_read64(qp->base + OTX2_CPT_LF_CTL);
201 ctl.s.ena = 0;
202 otx2_write64(ctl.u, qp->base + OTX2_CPT_LF_CTL);
203
204 /* Wait for instruction queue to become empty */
205 cnt = 0;
206 do {
207 inprog.u = otx2_read64(qp->base + OTX2_CPT_LF_INPROG);
208 if (inprog.s.grb_partial)
209 cnt = 0;
210 else
211 cnt++;
212 grp_ptr.u = otx2_read64(qp->base + OTX2_CPT_LF_Q_GRP_PTR);
213 } while ((cnt < 10) && (grp_ptr.s.nq_ptr != grp_ptr.s.dq_ptr));
214
215 cnt = 0;
216 do {
217 inprog.u = otx2_read64(qp->base + OTX2_CPT_LF_INPROG);
218 if ((inprog.s.inflight == 0) &&
219 (inprog.s.gwb_cnt < 40) &&
220 ((inprog.s.grb_cnt == 0) || (inprog.s.grb_cnt == 40)))
221 cnt++;
222 else
223 cnt = 0;
224 } while (cnt < 10);
225 }
226