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