xref: /dpdk/drivers/net/octeontx_ep/otx2_ep_vf.c (revision 7be78d02)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4 
5 #include <rte_common.h>
6 #include <rte_cycles.h>
7 #include "otx_ep_common.h"
8 #include "otx2_ep_vf.h"
9 
10 static void
otx2_vf_setup_global_iq_reg(struct otx_ep_device * otx_ep,int q_no)11 otx2_vf_setup_global_iq_reg(struct otx_ep_device *otx_ep, int q_no)
12 {
13 	volatile uint64_t reg_val = 0ull;
14 
15 	/* Select ES, RO, NS, RDSIZE,DPTR Format#0 for IQs
16 	 * IS_64B is by default enabled.
17 	 */
18 	reg_val = otx2_read64(otx_ep->hw_addr + SDP_VF_R_IN_CONTROL(q_no));
19 
20 	reg_val |= SDP_VF_R_IN_CTL_RDSIZE;
21 	reg_val |= SDP_VF_R_IN_CTL_IS_64B;
22 	reg_val |= SDP_VF_R_IN_CTL_ESR;
23 
24 	otx2_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_IN_CONTROL(q_no));
25 }
26 
27 static void
otx2_vf_setup_global_oq_reg(struct otx_ep_device * otx_ep,int q_no)28 otx2_vf_setup_global_oq_reg(struct otx_ep_device *otx_ep, int q_no)
29 {
30 	volatile uint64_t reg_val = 0ull;
31 
32 	reg_val = otx2_read64(otx_ep->hw_addr + SDP_VF_R_OUT_CONTROL(q_no));
33 
34 	reg_val &= ~(SDP_VF_R_OUT_CTL_IMODE);
35 	reg_val &= ~(SDP_VF_R_OUT_CTL_ROR_P);
36 	reg_val &= ~(SDP_VF_R_OUT_CTL_NSR_P);
37 	reg_val &= ~(SDP_VF_R_OUT_CTL_ROR_I);
38 	reg_val &= ~(SDP_VF_R_OUT_CTL_NSR_I);
39 	reg_val &= ~(SDP_VF_R_OUT_CTL_ES_I);
40 	reg_val &= ~(SDP_VF_R_OUT_CTL_ROR_D);
41 	reg_val &= ~(SDP_VF_R_OUT_CTL_NSR_D);
42 	reg_val &= ~(SDP_VF_R_OUT_CTL_ES_D);
43 
44 	/* INFO/DATA ptr swap is required  */
45 	reg_val |= (SDP_VF_R_OUT_CTL_ES_P);
46 
47 	otx2_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_OUT_CONTROL(q_no));
48 }
49 
50 static void
otx2_vf_setup_global_input_regs(struct otx_ep_device * otx_ep)51 otx2_vf_setup_global_input_regs(struct otx_ep_device *otx_ep)
52 {
53 	uint64_t q_no = 0ull;
54 
55 	for (q_no = 0; q_no < (otx_ep->sriov_info.rings_per_vf); q_no++)
56 		otx2_vf_setup_global_iq_reg(otx_ep, q_no);
57 }
58 
59 static void
otx2_vf_setup_global_output_regs(struct otx_ep_device * otx_ep)60 otx2_vf_setup_global_output_regs(struct otx_ep_device *otx_ep)
61 {
62 	uint32_t q_no;
63 
64 	for (q_no = 0; q_no < (otx_ep->sriov_info.rings_per_vf); q_no++)
65 		otx2_vf_setup_global_oq_reg(otx_ep, q_no);
66 }
67 
68 static void
otx2_vf_setup_device_regs(struct otx_ep_device * otx_ep)69 otx2_vf_setup_device_regs(struct otx_ep_device *otx_ep)
70 {
71 	otx2_vf_setup_global_input_regs(otx_ep);
72 	otx2_vf_setup_global_output_regs(otx_ep);
73 }
74 
75 static void
otx2_vf_setup_iq_regs(struct otx_ep_device * otx_ep,uint32_t iq_no)76 otx2_vf_setup_iq_regs(struct otx_ep_device *otx_ep, uint32_t iq_no)
77 {
78 	struct otx_ep_instr_queue *iq = otx_ep->instr_queue[iq_no];
79 	volatile uint64_t reg_val = 0ull;
80 
81 	reg_val = otx2_read64(otx_ep->hw_addr + SDP_VF_R_IN_CONTROL(iq_no));
82 
83 	/* Wait till IDLE to set to 1, not supposed to configure BADDR
84 	 * as long as IDLE is 0
85 	 */
86 	if (!(reg_val & SDP_VF_R_IN_CTL_IDLE)) {
87 		do {
88 			reg_val = otx2_read64(otx_ep->hw_addr +
89 					      SDP_VF_R_IN_CONTROL(iq_no));
90 		} while (!(reg_val & SDP_VF_R_IN_CTL_IDLE));
91 	}
92 
93 	/* Write the start of the input queue's ring and its size  */
94 	otx2_write64(iq->base_addr_dma, otx_ep->hw_addr +
95 		     SDP_VF_R_IN_INSTR_BADDR(iq_no));
96 	otx2_write64(iq->nb_desc, otx_ep->hw_addr +
97 		     SDP_VF_R_IN_INSTR_RSIZE(iq_no));
98 
99 	/* Remember the doorbell & instruction count register addr
100 	 * for this queue
101 	 */
102 	iq->doorbell_reg = (uint8_t *)otx_ep->hw_addr +
103 			   SDP_VF_R_IN_INSTR_DBELL(iq_no);
104 	iq->inst_cnt_reg = (uint8_t *)otx_ep->hw_addr +
105 			   SDP_VF_R_IN_CNTS(iq_no);
106 
107 	otx_ep_dbg("InstQ[%d]:dbell reg @ 0x%p inst_cnt_reg @ 0x%p",
108 		   iq_no, iq->doorbell_reg, iq->inst_cnt_reg);
109 
110 	do {
111 		reg_val = rte_read32(iq->inst_cnt_reg);
112 		rte_write32(reg_val, iq->inst_cnt_reg);
113 	} while (reg_val != 0);
114 
115 	/* IN INTR_THRESHOLD is set to max(FFFFFFFF) which disable the IN INTR
116 	 * to raise
117 	 */
118 	otx2_write64(OTX_EP_CLEAR_SDP_IN_INT_LVLS,
119 		     otx_ep->hw_addr + SDP_VF_R_IN_INT_LEVELS(iq_no));
120 }
121 
122 static void
otx2_vf_setup_oq_regs(struct otx_ep_device * otx_ep,uint32_t oq_no)123 otx2_vf_setup_oq_regs(struct otx_ep_device *otx_ep, uint32_t oq_no)
124 {
125 	volatile uint64_t reg_val = 0ull;
126 	uint64_t oq_ctl = 0ull;
127 	struct otx_ep_droq *droq = otx_ep->droq[oq_no];
128 
129 	/* Wait on IDLE to set to 1, supposed to configure BADDR
130 	 * as log as IDLE is 0
131 	 */
132 	reg_val = otx2_read64(otx_ep->hw_addr + SDP_VF_R_OUT_CONTROL(oq_no));
133 
134 	while (!(reg_val & SDP_VF_R_OUT_CTL_IDLE)) {
135 		reg_val = otx2_read64(otx_ep->hw_addr +
136 				      SDP_VF_R_OUT_CONTROL(oq_no));
137 	}
138 
139 	otx2_write64(droq->desc_ring_dma, otx_ep->hw_addr +
140 		     SDP_VF_R_OUT_SLIST_BADDR(oq_no));
141 	otx2_write64(droq->nb_desc, otx_ep->hw_addr +
142 		     SDP_VF_R_OUT_SLIST_RSIZE(oq_no));
143 
144 	oq_ctl = otx2_read64(otx_ep->hw_addr + SDP_VF_R_OUT_CONTROL(oq_no));
145 
146 	/* Clear the ISIZE and BSIZE (22-0) */
147 	oq_ctl &= ~(OTX_EP_CLEAR_ISIZE_BSIZE);
148 
149 	/* Populate the BSIZE (15-0) */
150 	oq_ctl |= (droq->buffer_size & OTX_EP_DROQ_BUFSZ_MASK);
151 
152 	otx2_write64(oq_ctl, otx_ep->hw_addr + SDP_VF_R_OUT_CONTROL(oq_no));
153 
154 	/* Mapped address of the pkt_sent and pkts_credit regs */
155 	droq->pkts_sent_reg = (uint8_t *)otx_ep->hw_addr +
156 			      SDP_VF_R_OUT_CNTS(oq_no);
157 	droq->pkts_credit_reg = (uint8_t *)otx_ep->hw_addr +
158 				SDP_VF_R_OUT_SLIST_DBELL(oq_no);
159 
160 	rte_write64(OTX_EP_CLEAR_OUT_INT_LVLS,
161 		    otx_ep->hw_addr + SDP_VF_R_OUT_INT_LEVELS(oq_no));
162 
163 	/* Clear PKT_CNT register */
164 	rte_write64(OTX_EP_CLEAR_SDP_OUT_PKT_CNT, (uint8_t *)otx_ep->hw_addr +
165 		    SDP_VF_R_OUT_PKT_CNT(oq_no));
166 
167 	/* Clear the OQ doorbell  */
168 	rte_write32(OTX_EP_CLEAR_SLIST_DBELL, droq->pkts_credit_reg);
169 	while ((rte_read32(droq->pkts_credit_reg) != 0ull)) {
170 		rte_write32(OTX_EP_CLEAR_SLIST_DBELL, droq->pkts_credit_reg);
171 		rte_delay_ms(1);
172 	}
173 	otx_ep_dbg("SDP_R[%d]_credit:%x", oq_no,
174 		   rte_read32(droq->pkts_credit_reg));
175 
176 	/* Clear the OQ_OUT_CNTS doorbell  */
177 	reg_val = rte_read32(droq->pkts_sent_reg);
178 	rte_write32((uint32_t)reg_val, droq->pkts_sent_reg);
179 
180 	otx_ep_dbg("SDP_R[%d]_sent: %x", oq_no,
181 		   rte_read32(droq->pkts_sent_reg));
182 
183 	while (((rte_read32(droq->pkts_sent_reg)) != 0ull)) {
184 		reg_val = rte_read32(droq->pkts_sent_reg);
185 		rte_write32((uint32_t)reg_val, droq->pkts_sent_reg);
186 		rte_delay_ms(1);
187 	}
188 	otx_ep_dbg("SDP_R[%d]_sent: %x", oq_no,
189 		   rte_read32(droq->pkts_sent_reg));
190 }
191 
192 static int
otx2_vf_enable_iq(struct otx_ep_device * otx_ep,uint32_t q_no)193 otx2_vf_enable_iq(struct otx_ep_device *otx_ep, uint32_t q_no)
194 {
195 	uint64_t loop = SDP_VF_BUSY_LOOP_COUNT;
196 	uint64_t reg_val = 0ull;
197 
198 	/* Resetting doorbells during IQ enabling also to handle abrupt
199 	 * guest reboot. IQ reset does not clear the doorbells.
200 	 */
201 	otx2_write64(0xFFFFFFFF, otx_ep->hw_addr +
202 		     SDP_VF_R_IN_INSTR_DBELL(q_no));
203 
204 	while (((otx2_read64(otx_ep->hw_addr +
205 		 SDP_VF_R_IN_INSTR_DBELL(q_no))) != 0ull) && loop--) {
206 		rte_delay_ms(1);
207 	}
208 
209 	if (!loop) {
210 		otx_ep_err("INSTR DBELL not coming back to 0\n");
211 		return -EIO;
212 	}
213 
214 	reg_val = otx2_read64(otx_ep->hw_addr + SDP_VF_R_IN_ENABLE(q_no));
215 	reg_val |= 0x1ull;
216 
217 	otx2_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_IN_ENABLE(q_no));
218 
219 	otx_ep_info("IQ[%d] enable done", q_no);
220 
221 	return 0;
222 }
223 
224 static int
otx2_vf_enable_oq(struct otx_ep_device * otx_ep,uint32_t q_no)225 otx2_vf_enable_oq(struct otx_ep_device *otx_ep, uint32_t q_no)
226 {
227 	uint64_t reg_val = 0ull;
228 
229 	reg_val = otx2_read64(otx_ep->hw_addr + SDP_VF_R_OUT_ENABLE(q_no));
230 	reg_val |= 0x1ull;
231 	otx2_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_OUT_ENABLE(q_no));
232 
233 	otx_ep_info("OQ[%d] enable done", q_no);
234 
235 	return 0;
236 }
237 
238 static int
otx2_vf_enable_io_queues(struct otx_ep_device * otx_ep)239 otx2_vf_enable_io_queues(struct otx_ep_device *otx_ep)
240 {
241 	uint32_t q_no = 0;
242 	int ret;
243 
244 	for (q_no = 0; q_no < otx_ep->nb_tx_queues; q_no++) {
245 		ret = otx2_vf_enable_iq(otx_ep, q_no);
246 		if (ret)
247 			return ret;
248 	}
249 
250 	for (q_no = 0; q_no < otx_ep->nb_rx_queues; q_no++)
251 		otx2_vf_enable_oq(otx_ep, q_no);
252 
253 	return 0;
254 }
255 
256 static void
otx2_vf_disable_iq(struct otx_ep_device * otx_ep,uint32_t q_no)257 otx2_vf_disable_iq(struct otx_ep_device *otx_ep, uint32_t q_no)
258 {
259 	uint64_t reg_val = 0ull;
260 
261 	/* Reset the doorbell register for this Input Queue. */
262 	reg_val = otx2_read64(otx_ep->hw_addr + SDP_VF_R_IN_ENABLE(q_no));
263 	reg_val &= ~0x1ull;
264 
265 	otx2_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_IN_ENABLE(q_no));
266 }
267 
268 static void
otx2_vf_disable_oq(struct otx_ep_device * otx_ep,uint32_t q_no)269 otx2_vf_disable_oq(struct otx_ep_device *otx_ep, uint32_t q_no)
270 {
271 	volatile uint64_t reg_val = 0ull;
272 
273 	reg_val = otx2_read64(otx_ep->hw_addr + SDP_VF_R_OUT_ENABLE(q_no));
274 	reg_val &= ~0x1ull;
275 
276 	otx2_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_OUT_ENABLE(q_no));
277 }
278 
279 static void
otx2_vf_disable_io_queues(struct otx_ep_device * otx_ep)280 otx2_vf_disable_io_queues(struct otx_ep_device *otx_ep)
281 {
282 	uint32_t q_no = 0;
283 
284 	for (q_no = 0; q_no < otx_ep->sriov_info.rings_per_vf; q_no++) {
285 		otx2_vf_disable_iq(otx_ep, q_no);
286 		otx2_vf_disable_oq(otx_ep, q_no);
287 	}
288 }
289 
290 static const struct otx_ep_config default_otx2_ep_conf = {
291 	/* IQ attributes */
292 	.iq                        = {
293 		.max_iqs           = OTX_EP_CFG_IO_QUEUES,
294 		.instr_type        = OTX_EP_64BYTE_INSTR,
295 		.pending_list_size = (OTX_EP_MAX_IQ_DESCRIPTORS *
296 				      OTX_EP_CFG_IO_QUEUES),
297 	},
298 
299 	/* OQ attributes */
300 	.oq                        = {
301 		.max_oqs           = OTX_EP_CFG_IO_QUEUES,
302 		.info_ptr          = OTX_EP_OQ_INFOPTR_MODE,
303 		.refill_threshold  = OTX_EP_OQ_REFIL_THRESHOLD,
304 	},
305 
306 	.num_iqdef_descs           = OTX_EP_MAX_IQ_DESCRIPTORS,
307 	.num_oqdef_descs           = OTX_EP_MAX_OQ_DESCRIPTORS,
308 	.oqdef_buf_size            = OTX_EP_OQ_BUF_SIZE,
309 };
310 
311 static const struct otx_ep_config*
otx2_ep_get_defconf(struct otx_ep_device * otx_ep_dev __rte_unused)312 otx2_ep_get_defconf(struct otx_ep_device *otx_ep_dev __rte_unused)
313 {
314 	const struct otx_ep_config *default_conf = NULL;
315 
316 	default_conf = &default_otx2_ep_conf;
317 
318 	return default_conf;
319 }
320 
321 int
otx2_ep_vf_setup_device(struct otx_ep_device * otx_ep)322 otx2_ep_vf_setup_device(struct otx_ep_device *otx_ep)
323 {
324 	uint64_t reg_val = 0ull;
325 
326 	/* If application doesn't provide its conf, use driver default conf */
327 	if (otx_ep->conf == NULL) {
328 		otx_ep->conf = otx2_ep_get_defconf(otx_ep);
329 		if (otx_ep->conf == NULL) {
330 			otx_ep_err("SDP VF default config not found");
331 			return -ENOENT;
332 		}
333 		otx_ep_info("Default config is used");
334 	}
335 
336 	/* Get IOQs (RPVF] count */
337 	reg_val = otx2_read64(otx_ep->hw_addr + SDP_VF_R_IN_CONTROL(0));
338 
339 	otx_ep->sriov_info.rings_per_vf = ((reg_val >> SDP_VF_R_IN_CTL_RPVF_POS)
340 					  & SDP_VF_R_IN_CTL_RPVF_MASK);
341 
342 	otx_ep_info("SDP RPVF: %d", otx_ep->sriov_info.rings_per_vf);
343 
344 	otx_ep->fn_list.setup_iq_regs       = otx2_vf_setup_iq_regs;
345 	otx_ep->fn_list.setup_oq_regs       = otx2_vf_setup_oq_regs;
346 
347 	otx_ep->fn_list.setup_device_regs   = otx2_vf_setup_device_regs;
348 
349 	otx_ep->fn_list.enable_io_queues    = otx2_vf_enable_io_queues;
350 	otx_ep->fn_list.disable_io_queues   = otx2_vf_disable_io_queues;
351 
352 	otx_ep->fn_list.enable_iq           = otx2_vf_enable_iq;
353 	otx_ep->fn_list.disable_iq          = otx2_vf_disable_iq;
354 
355 	otx_ep->fn_list.enable_oq           = otx2_vf_enable_oq;
356 	otx_ep->fn_list.disable_oq          = otx2_vf_disable_oq;
357 
358 	return 0;
359 }
360