Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : :
5 : : #include <errno.h>
6 : :
7 : : #include <rte_common.h>
8 : : #include <rte_cycles.h>
9 : : #include <rte_memzone.h>
10 : : #include "otx_ep_common.h"
11 : : #include "otx2_ep_vf.h"
12 : :
13 : : static int otx2_vf_enable_rxq_intr(struct otx_ep_device *otx_epvf,
14 : : uint16_t q_no);
15 : :
16 : : static int
17 : 0 : otx2_vf_reset_iq(struct otx_ep_device *otx_ep, int q_no)
18 : : {
19 : : int loop = SDP_VF_BUSY_LOOP_COUNT;
20 : 0 : volatile uint64_t d64 = 0ull;
21 : :
22 : : /* There is no RST for a ring.
23 : : * Clear all registers one by one after disabling the ring
24 : : */
25 : :
26 : 0 : otx2_write64(d64, otx_ep->hw_addr + SDP_VF_R_IN_ENABLE(q_no));
27 : 0 : otx2_write64(d64, otx_ep->hw_addr + SDP_VF_R_IN_INSTR_BADDR(q_no));
28 : 0 : otx2_write64(d64, otx_ep->hw_addr + SDP_VF_R_IN_INSTR_RSIZE(q_no));
29 : :
30 : 0 : d64 = 0xFFFFFFFF; /* ~0ull */
31 : 0 : otx2_write64(d64, otx_ep->hw_addr + SDP_VF_R_IN_INSTR_DBELL(q_no));
32 : 0 : d64 = otx2_read64(otx_ep->hw_addr + SDP_VF_R_IN_INSTR_DBELL(q_no));
33 : :
34 [ # # # # ]: 0 : while ((d64 != 0) && loop--) {
35 : : rte_delay_ms(1);
36 : 0 : d64 = otx2_read64(otx_ep->hw_addr +
37 : : SDP_VF_R_IN_INSTR_DBELL(q_no));
38 : : }
39 [ # # ]: 0 : if (loop < 0) {
40 : 0 : otx_ep_err("%s: doorbell init retry limit exceeded.\n", __func__);
41 : 0 : return -EIO;
42 : : }
43 : :
44 : : loop = SDP_VF_BUSY_LOOP_COUNT;
45 : : do {
46 : 0 : d64 = otx2_read64(otx_ep->hw_addr + SDP_VF_R_IN_CNTS(q_no));
47 : 0 : otx2_write64(d64, otx_ep->hw_addr + SDP_VF_R_IN_CNTS(q_no));
48 : : rte_delay_ms(1);
49 [ # # # # ]: 0 : } while ((d64 & ~SDP_VF_R_IN_CNTS_OUT_INT) != 0 && loop--);
50 [ # # ]: 0 : if (loop < 0) {
51 : 0 : otx_ep_err("%s: in_cnts init retry limit exceeded.\n", __func__);
52 : 0 : return -EIO;
53 : : }
54 : :
55 : 0 : d64 = 0ull;
56 : 0 : otx2_write64(d64, otx_ep->hw_addr + SDP_VF_R_IN_INT_LEVELS(q_no));
57 : 0 : otx2_write64(d64, otx_ep->hw_addr + SDP_VF_R_IN_PKT_CNT(q_no));
58 : 0 : otx2_write64(d64, otx_ep->hw_addr + SDP_VF_R_IN_BYTE_CNT(q_no));
59 : :
60 : 0 : return 0;
61 : : }
62 : :
63 : : static int
64 : 0 : otx2_vf_reset_oq(struct otx_ep_device *otx_ep, int q_no)
65 : : {
66 : : int loop = SDP_VF_BUSY_LOOP_COUNT;
67 : 0 : volatile uint64_t d64 = 0ull;
68 : :
69 : 0 : otx2_write64(d64, otx_ep->hw_addr + SDP_VF_R_OUT_ENABLE(q_no));
70 : :
71 : 0 : otx2_write64(d64, otx_ep->hw_addr + SDP_VF_R_OUT_SLIST_BADDR(q_no));
72 : :
73 : 0 : otx2_write64(d64, otx_ep->hw_addr + SDP_VF_R_OUT_SLIST_RSIZE(q_no));
74 : :
75 : 0 : d64 = 0xFFFFFFFF;
76 : 0 : otx2_write64(d64, otx_ep->hw_addr + SDP_VF_R_OUT_SLIST_DBELL(q_no));
77 : 0 : d64 = otx2_read64(otx_ep->hw_addr + SDP_VF_R_OUT_SLIST_DBELL(q_no));
78 [ # # # # ]: 0 : while ((d64 != 0) && loop--) {
79 : : rte_delay_ms(1);
80 : 0 : d64 = otx2_read64(otx_ep->hw_addr +
81 : : SDP_VF_R_OUT_SLIST_DBELL(q_no));
82 : : }
83 [ # # ]: 0 : if (loop < 0) {
84 : 0 : otx_ep_err("%s: doorbell init retry limit exceeded.\n", __func__);
85 : 0 : return -EIO;
86 : : }
87 : :
88 [ # # ]: 0 : if (otx2_read64(otx_ep->hw_addr + SDP_VF_R_OUT_CNTS(q_no))
89 [ # # ]: 0 : & SDP_VF_R_OUT_CNTS_OUT_INT) {
90 : : /*
91 : : * The OUT_INT bit is set. This interrupt must be enabled in
92 : : * order to clear the interrupt. Interrupts are disabled
93 : : * at the end of this function.
94 : : */
95 : : union out_int_lvl_t out_int_lvl;
96 : :
97 : 0 : out_int_lvl.d64 = otx2_read64(otx_ep->hw_addr +
98 : : SDP_VF_R_OUT_INT_LEVELS(q_no));
99 : 0 : out_int_lvl.s.time_cnt_en = 1;
100 : 0 : out_int_lvl.s.cnt = 0;
101 : 0 : otx2_write64(out_int_lvl.d64, otx_ep->hw_addr +
102 : : SDP_VF_R_OUT_INT_LEVELS(q_no));
103 : : }
104 : :
105 : : loop = SDP_VF_BUSY_LOOP_COUNT;
106 : : do {
107 : 0 : d64 = otx2_read64(otx_ep->hw_addr + SDP_VF_R_OUT_CNTS(q_no));
108 : 0 : otx2_write64(d64, otx_ep->hw_addr + SDP_VF_R_OUT_CNTS(q_no));
109 : : rte_delay_ms(1);
110 [ # # # # ]: 0 : } while ((d64 & ~SDP_VF_R_OUT_CNTS_IN_INT) != 0 && loop--);
111 [ # # ]: 0 : if (loop < 0) {
112 : 0 : otx_ep_err("%s: out_cnts init retry limit exceeded.\n", __func__);
113 : 0 : return -EIO;
114 : : }
115 : :
116 : 0 : d64 = 0ull;
117 : 0 : otx2_write64(d64, otx_ep->hw_addr + SDP_VF_R_OUT_INT_LEVELS(q_no));
118 : 0 : otx2_write64(d64, otx_ep->hw_addr + SDP_VF_R_OUT_PKT_CNT(q_no));
119 : 0 : otx2_write64(d64, otx_ep->hw_addr + SDP_VF_R_OUT_BYTE_CNT(q_no));
120 : :
121 : 0 : return 0;
122 : : }
123 : :
124 : : static void
125 : 0 : otx2_vf_setup_global_iq_reg(struct otx_ep_device *otx_ep, int q_no)
126 : : {
127 : 0 : volatile uint64_t reg_val = 0ull;
128 : :
129 : : /* Select ES, RO, NS, RDSIZE,DPTR Format#0 for IQs
130 : : * IS_64B is by default enabled.
131 : : */
132 : 0 : reg_val = oct_ep_read64(otx_ep->hw_addr + SDP_VF_R_IN_CONTROL(q_no));
133 : :
134 : 0 : reg_val |= SDP_VF_R_IN_CTL_RDSIZE;
135 : 0 : reg_val |= SDP_VF_R_IN_CTL_IS_64B;
136 : 0 : reg_val |= SDP_VF_R_IN_CTL_ESR;
137 : :
138 : 0 : oct_ep_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_IN_CONTROL(q_no));
139 : 0 : }
140 : :
141 : : static void
142 : 0 : otx2_vf_setup_global_oq_reg(struct otx_ep_device *otx_ep, int q_no)
143 : : {
144 : 0 : volatile uint64_t reg_val = 0ull;
145 : :
146 : 0 : reg_val = oct_ep_read64(otx_ep->hw_addr + SDP_VF_R_OUT_CONTROL(q_no));
147 : :
148 : 0 : reg_val &= ~(SDP_VF_R_OUT_CTL_IMODE);
149 : 0 : reg_val &= ~(SDP_VF_R_OUT_CTL_ROR_P);
150 : 0 : reg_val &= ~(SDP_VF_R_OUT_CTL_NSR_P);
151 : 0 : reg_val &= ~(SDP_VF_R_OUT_CTL_ROR_I);
152 : 0 : reg_val &= ~(SDP_VF_R_OUT_CTL_NSR_I);
153 : 0 : reg_val &= ~(SDP_VF_R_OUT_CTL_ES_I);
154 : 0 : reg_val &= ~(SDP_VF_R_OUT_CTL_ROR_D);
155 : 0 : reg_val &= ~(SDP_VF_R_OUT_CTL_NSR_D);
156 : 0 : reg_val &= ~(SDP_VF_R_OUT_CTL_ES_D);
157 : :
158 : : /* INFO/DATA ptr swap is required */
159 : 0 : reg_val |= (SDP_VF_R_OUT_CTL_ES_P);
160 : :
161 : 0 : oct_ep_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_OUT_CONTROL(q_no));
162 : 0 : }
163 : :
164 : : static int
165 : : otx2_vf_reset_input_queues(struct otx_ep_device *otx_ep)
166 : : {
167 : : uint32_t q_no = 0;
168 : : int ret = 0;
169 : :
170 [ # # ]: 0 : for (q_no = 0; q_no < otx_ep->sriov_info.rings_per_vf; q_no++) {
171 : 0 : ret = otx2_vf_reset_iq(otx_ep, q_no);
172 [ # # ]: 0 : if (ret)
173 : : return ret;
174 : : }
175 : :
176 : : return ret;
177 : : }
178 : :
179 : : static int
180 : : otx2_vf_reset_output_queues(struct otx_ep_device *otx_ep)
181 : : {
182 : : uint64_t q_no = 0ull;
183 : : int ret = 0;
184 : :
185 [ # # ]: 0 : for (q_no = 0; q_no < otx_ep->sriov_info.rings_per_vf; q_no++) {
186 : 0 : ret = otx2_vf_reset_oq(otx_ep, q_no);
187 [ # # ]: 0 : if (ret)
188 : : return ret;
189 : : }
190 : :
191 : : return ret;
192 : : }
193 : :
194 : : static int
195 : 0 : otx2_vf_setup_global_input_regs(struct otx_ep_device *otx_ep)
196 : : {
197 : : uint64_t q_no = 0ull;
198 : : int ret = 0;
199 : :
200 : : ret = otx2_vf_reset_input_queues(otx_ep);
201 [ # # ]: 0 : if (ret)
202 : : return ret;
203 : :
204 [ # # ]: 0 : for (q_no = 0; q_no < (otx_ep->sriov_info.rings_per_vf); q_no++)
205 : 0 : otx2_vf_setup_global_iq_reg(otx_ep, q_no);
206 : : return ret;
207 : : }
208 : :
209 : : static int
210 : 0 : otx2_vf_setup_global_output_regs(struct otx_ep_device *otx_ep)
211 : : {
212 : : uint32_t q_no;
213 : : int ret = 0;
214 : :
215 : : ret = otx2_vf_reset_output_queues(otx_ep);
216 [ # # ]: 0 : if (ret)
217 : : return ret;
218 [ # # ]: 0 : for (q_no = 0; q_no < (otx_ep->sriov_info.rings_per_vf); q_no++)
219 : 0 : otx2_vf_setup_global_oq_reg(otx_ep, q_no);
220 : : return ret;
221 : : }
222 : :
223 : : static int
224 : 0 : otx2_vf_setup_device_regs(struct otx_ep_device *otx_ep)
225 : : {
226 : : int ret;
227 : :
228 : 0 : ret = otx2_vf_setup_global_input_regs(otx_ep);
229 [ # # ]: 0 : if (ret)
230 : : return ret;
231 : 0 : ret = otx2_vf_setup_global_output_regs(otx_ep);
232 : 0 : return ret;
233 : : }
234 : :
235 : : static int
236 : 0 : otx2_vf_setup_iq_regs(struct otx_ep_device *otx_ep, uint32_t iq_no)
237 : : {
238 : 0 : struct otx_ep_instr_queue *iq = otx_ep->instr_queue[iq_no];
239 : 0 : volatile uint64_t reg_val = 0ull;
240 : : uint64_t ism_addr;
241 : : int loop = SDP_VF_BUSY_LOOP_COUNT;
242 : :
243 [ # # ]: 0 : reg_val = oct_ep_read64(otx_ep->hw_addr + SDP_VF_R_IN_CONTROL(iq_no));
244 : :
245 : : /* Wait till IDLE to set to 1, not supposed to configure BADDR
246 : : * as long as IDLE is 0
247 : : */
248 [ # # ]: 0 : if (!(reg_val & SDP_VF_R_IN_CTL_IDLE)) {
249 : : do {
250 : 0 : reg_val = oct_ep_read64(otx_ep->hw_addr + SDP_VF_R_IN_CONTROL(iq_no));
251 [ # # # # ]: 0 : } while ((!(reg_val & SDP_VF_R_IN_CTL_IDLE)) && loop--);
252 : : }
253 : :
254 [ # # ]: 0 : if (loop < 0) {
255 : 0 : otx_ep_err("IDLE bit is not set\n");
256 : 0 : return -EIO;
257 : : }
258 : :
259 : : /* Configure input queue instruction size. */
260 [ # # ]: 0 : if (otx_ep->conf->iq.instr_type == OTX_EP_32BYTE_INSTR)
261 : 0 : reg_val &= ~(SDP_VF_R_IN_CTL_IS_64B);
262 : : else
263 : 0 : reg_val |= SDP_VF_R_IN_CTL_IS_64B;
264 : 0 : oct_ep_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_IN_CONTROL(iq_no));
265 : 0 : iq->desc_size = otx_ep->conf->iq.instr_type;
266 : :
267 : : /* Write the start of the input queue's ring and its size */
268 : 0 : oct_ep_write64(iq->base_addr_dma, otx_ep->hw_addr + SDP_VF_R_IN_INSTR_BADDR(iq_no));
269 : 0 : oct_ep_write64(iq->nb_desc, otx_ep->hw_addr + SDP_VF_R_IN_INSTR_RSIZE(iq_no));
270 : :
271 : : /* Remember the doorbell & instruction count register addr
272 : : * for this queue
273 : : */
274 : 0 : iq->doorbell_reg = (uint8_t *)otx_ep->hw_addr + SDP_VF_R_IN_INSTR_DBELL(iq_no);
275 : 0 : iq->inst_cnt_reg = (uint8_t *)otx_ep->hw_addr + SDP_VF_R_IN_CNTS(iq_no);
276 : :
277 : 0 : otx_ep_dbg("InstQ[%d]:dbell reg @ 0x%p inst_cnt_reg @ 0x%p",
278 : : iq_no, iq->doorbell_reg, iq->inst_cnt_reg);
279 : : loop = SDP_VF_BUSY_LOOP_COUNT;
280 : : do {
281 : 0 : reg_val = rte_read32(iq->inst_cnt_reg);
282 : 0 : rte_write32(reg_val, iq->inst_cnt_reg);
283 [ # # # # ]: 0 : } while (reg_val != 0 && loop--);
284 : :
285 [ # # ]: 0 : if (loop < 0) {
286 : 0 : otx_ep_err("INST CNT REGISTER is not zero\n");
287 : 0 : return -EIO;
288 : : }
289 : :
290 : : /* IN INTR_THRESHOLD is set to max(FFFFFFFF) which disable the IN INTR
291 : : * to raise
292 : : */
293 : 0 : oct_ep_write64(OTX_EP_CLEAR_SDP_IN_INT_LVLS,
294 : : otx_ep->hw_addr + SDP_VF_R_IN_INT_LEVELS(iq_no));
295 : :
296 : : /* Set up IQ ISM registers and structures */
297 : 0 : ism_addr = (otx_ep->ism_buffer_mz->iova | OTX2_EP_ISM_EN
298 : 0 : | OTX2_EP_ISM_MSIX_DIS)
299 : 0 : + OTX2_EP_IQ_ISM_OFFSET(iq_no);
300 : 0 : oct_ep_write64(ism_addr, (uint8_t *)otx_ep->hw_addr +
301 : : SDP_VF_R_IN_CNTS_ISM(iq_no));
302 : 0 : iq->inst_cnt_ism =
303 : 0 : (uint32_t *)((uint8_t *)otx_ep->ism_buffer_mz->addr
304 : : + OTX2_EP_IQ_ISM_OFFSET(iq_no));
305 : 0 : otx_ep_err("SDP_R[%d] INST Q ISM virt: %p, dma: 0x%x", iq_no,
306 : : (void *)iq->inst_cnt_ism,
307 : : (unsigned int)ism_addr);
308 : 0 : *iq->inst_cnt_ism = 0;
309 : 0 : iq->inst_cnt_prev = 0;
310 : 0 : iq->partial_ih = ((uint64_t)otx_ep->pkind) << 36;
311 : :
312 : 0 : return 0;
313 : : }
314 : :
315 : : static int
316 : 0 : otx2_vf_setup_oq_regs(struct otx_ep_device *otx_ep, uint32_t oq_no)
317 : : {
318 : 0 : volatile uint64_t reg_val = 0ull;
319 : : uint64_t oq_ctl = 0ull;
320 : : uint64_t ism_addr;
321 : : int loop = OTX_EP_BUSY_LOOP_COUNT;
322 : 0 : struct otx_ep_droq *droq = otx_ep->droq[oq_no];
323 : :
324 : : /* Wait on IDLE to set to 1, supposed to configure BADDR
325 : : * as long as IDLE is 0
326 : : */
327 : 0 : reg_val = oct_ep_read64(otx_ep->hw_addr + SDP_VF_R_OUT_CONTROL(oq_no));
328 : :
329 [ # # # # ]: 0 : while ((!(reg_val & SDP_VF_R_OUT_CTL_IDLE)) && loop--) {
330 : 0 : reg_val = oct_ep_read64(otx_ep->hw_addr + SDP_VF_R_OUT_CONTROL(oq_no));
331 : : rte_delay_ms(1);
332 : : }
333 : :
334 [ # # ]: 0 : if (loop < 0) {
335 : 0 : otx_ep_err("OUT CNT REGISTER value is zero\n");
336 : 0 : return -EIO;
337 : : }
338 : :
339 : 0 : oct_ep_write64(droq->desc_ring_dma, otx_ep->hw_addr + SDP_VF_R_OUT_SLIST_BADDR(oq_no));
340 : 0 : oct_ep_write64(droq->nb_desc, otx_ep->hw_addr + SDP_VF_R_OUT_SLIST_RSIZE(oq_no));
341 : :
342 : 0 : oq_ctl = oct_ep_read64(otx_ep->hw_addr + SDP_VF_R_OUT_CONTROL(oq_no));
343 : :
344 : : /* Clear the ISIZE and BSIZE (22-0) */
345 : 0 : oq_ctl &= ~(OTX_EP_CLEAR_ISIZE_BSIZE);
346 : :
347 : : /* Populate the BSIZE (15-0) */
348 : 0 : oq_ctl |= (droq->buffer_size & OTX_EP_DROQ_BUFSZ_MASK);
349 : :
350 : : oct_ep_write64(oq_ctl, otx_ep->hw_addr + SDP_VF_R_OUT_CONTROL(oq_no));
351 : :
352 : : /* Mapped address of the pkt_sent and pkts_credit regs */
353 : 0 : droq->pkts_sent_reg = (uint8_t *)otx_ep->hw_addr + SDP_VF_R_OUT_CNTS(oq_no);
354 : 0 : droq->pkts_credit_reg = (uint8_t *)otx_ep->hw_addr + SDP_VF_R_OUT_SLIST_DBELL(oq_no);
355 : :
356 : 0 : rte_write64(OTX_EP_CLEAR_OUT_INT_LVLS, otx_ep->hw_addr + SDP_VF_R_OUT_INT_LEVELS(oq_no));
357 : :
358 : : /* Clear PKT_CNT register */
359 : 0 : rte_write64(OTX_EP_CLEAR_SDP_OUT_PKT_CNT, (uint8_t *)otx_ep->hw_addr +
360 : 0 : SDP_VF_R_OUT_PKT_CNT(oq_no));
361 : :
362 : : /* Clear the OQ doorbell */
363 : : loop = OTX_EP_BUSY_LOOP_COUNT;
364 : 0 : rte_write32(OTX_EP_CLEAR_SLIST_DBELL, droq->pkts_credit_reg);
365 [ # # # # ]: 0 : while ((rte_read32(droq->pkts_credit_reg) != 0ull) && loop--) {
366 : 0 : rte_write32(OTX_EP_CLEAR_SLIST_DBELL, droq->pkts_credit_reg);
367 : : rte_delay_ms(1);
368 : : }
369 : :
370 [ # # ]: 0 : if (loop < 0) {
371 : 0 : otx_ep_err("Packets credit register value is not cleared\n");
372 : 0 : return -EIO;
373 : : }
374 : 0 : otx_ep_dbg("SDP_R[%d]_credit:%x", oq_no, rte_read32(droq->pkts_credit_reg));
375 : :
376 : : /* Clear the OQ_OUT_CNTS doorbell */
377 : 0 : reg_val = rte_read32(droq->pkts_sent_reg);
378 : 0 : rte_write32((uint32_t)reg_val, droq->pkts_sent_reg);
379 : :
380 : 0 : otx_ep_dbg("SDP_R[%d]_sent: %x", oq_no, rte_read32(droq->pkts_sent_reg));
381 : :
382 : : /* Set up ISM registers and structures */
383 : 0 : ism_addr = (otx_ep->ism_buffer_mz->iova | OTX2_EP_ISM_EN
384 : 0 : | OTX2_EP_ISM_MSIX_DIS)
385 : 0 : + OTX2_EP_OQ_ISM_OFFSET(oq_no);
386 : 0 : oct_ep_write64(ism_addr, (uint8_t *)otx_ep->hw_addr +
387 : : SDP_VF_R_OUT_CNTS_ISM(oq_no));
388 : 0 : droq->pkts_sent_ism =
389 : 0 : (uint32_t *)((uint8_t *)otx_ep->ism_buffer_mz->addr
390 : : + OTX2_EP_OQ_ISM_OFFSET(oq_no));
391 : 0 : otx_ep_err("SDP_R[%d] OQ ISM virt: %p, dma: 0x%x", oq_no,
392 : : (void *)droq->pkts_sent_ism,
393 : : (unsigned int)ism_addr);
394 : 0 : *droq->pkts_sent_ism = 0;
395 : 0 : droq->pkts_sent_prev = 0;
396 : :
397 : : loop = SDP_VF_BUSY_LOOP_COUNT;
398 [ # # # # ]: 0 : while (((rte_read32(droq->pkts_sent_reg)) != 0ull) && loop--) {
399 : 0 : reg_val = rte_read32(droq->pkts_sent_reg);
400 : 0 : rte_write32((uint32_t)reg_val, droq->pkts_sent_reg);
401 : : rte_delay_ms(1);
402 : : }
403 [ # # ]: 0 : if (loop < 0)
404 : : return -EIO;
405 : 0 : otx_ep_dbg("SDP_R[%d]_sent: %x", oq_no,
406 : : rte_read32(droq->pkts_sent_reg));
407 : :
408 : 0 : return 0;
409 : : }
410 : :
411 : : static int
412 : 0 : otx2_vf_enable_iq(struct otx_ep_device *otx_ep, uint32_t q_no)
413 : : {
414 : : int loop = SDP_VF_BUSY_LOOP_COUNT;
415 : : uint64_t reg_val = 0ull;
416 : :
417 : : /* Resetting doorbells during IQ enabling also to handle abrupt
418 : : * guest reboot. IQ reset does not clear the doorbells.
419 : : */
420 : 0 : oct_ep_write64(0xFFFFFFFF, otx_ep->hw_addr + SDP_VF_R_IN_INSTR_DBELL(q_no));
421 : :
422 [ # # ]: 0 : while (((oct_ep_read64(otx_ep->hw_addr +
423 [ # # # # ]: 0 : SDP_VF_R_IN_INSTR_DBELL(q_no))) != 0ull) && loop--) {
424 : : rte_delay_ms(1);
425 : : }
426 : :
427 [ # # ]: 0 : if (loop < 0) {
428 : 0 : otx_ep_err("INSTR DBELL not coming back to 0\n");
429 : 0 : return -EIO;
430 : : }
431 : :
432 : 0 : reg_val = oct_ep_read64(otx_ep->hw_addr + SDP_VF_R_IN_ENABLE(q_no));
433 : 0 : reg_val |= 0x1ull;
434 : :
435 : : oct_ep_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_IN_ENABLE(q_no));
436 : :
437 : 0 : otx_ep_info("IQ[%d] enable done", q_no);
438 : :
439 : 0 : return 0;
440 : : }
441 : :
442 : : static int
443 : 0 : otx2_vf_enable_oq(struct otx_ep_device *otx_ep, uint32_t q_no)
444 : : {
445 : : uint64_t reg_val = 0ull;
446 : :
447 : 0 : reg_val = oct_ep_read64(otx_ep->hw_addr + SDP_VF_R_OUT_ENABLE(q_no));
448 : 0 : reg_val |= 0x1ull;
449 : : oct_ep_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_OUT_ENABLE(q_no));
450 : :
451 : 0 : otx_ep_info("OQ[%d] enable done", q_no);
452 : :
453 : 0 : return 0;
454 : : }
455 : :
456 : : static int
457 : 0 : otx2_vf_enable_io_queues(struct otx_ep_device *otx_ep)
458 : : {
459 : : uint32_t q_no = 0;
460 : : int ret;
461 : :
462 [ # # ]: 0 : for (q_no = 0; q_no < otx_ep->nb_tx_queues; q_no++) {
463 : 0 : ret = otx2_vf_enable_iq(otx_ep, q_no);
464 [ # # ]: 0 : if (ret)
465 : 0 : return ret;
466 : : }
467 : :
468 [ # # ]: 0 : for (q_no = 0; q_no < otx_ep->nb_rx_queues; q_no++)
469 : 0 : otx2_vf_enable_oq(otx_ep, q_no);
470 : :
471 : : return 0;
472 : : }
473 : :
474 : : static void
475 : 0 : otx2_vf_disable_iq(struct otx_ep_device *otx_ep, uint32_t q_no)
476 : : {
477 : : uint64_t reg_val = 0ull;
478 : :
479 : : /* Reset the doorbell register for this Input Queue. */
480 : 0 : reg_val = oct_ep_read64(otx_ep->hw_addr + SDP_VF_R_IN_ENABLE(q_no));
481 : 0 : reg_val &= ~0x1ull;
482 : :
483 : : oct_ep_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_IN_ENABLE(q_no));
484 : 0 : }
485 : :
486 : : static void
487 : 0 : otx2_vf_disable_oq(struct otx_ep_device *otx_ep, uint32_t q_no)
488 : : {
489 : 0 : volatile uint64_t reg_val = 0ull;
490 : :
491 : 0 : reg_val = oct_ep_read64(otx_ep->hw_addr + SDP_VF_R_OUT_ENABLE(q_no));
492 : 0 : reg_val &= ~0x1ull;
493 : :
494 : 0 : oct_ep_write64(reg_val, otx_ep->hw_addr + SDP_VF_R_OUT_ENABLE(q_no));
495 : 0 : }
496 : :
497 : : static void
498 : 0 : otx2_vf_disable_io_queues(struct otx_ep_device *otx_ep)
499 : : {
500 : : uint32_t q_no = 0;
501 : :
502 [ # # ]: 0 : for (q_no = 0; q_no < otx_ep->sriov_info.rings_per_vf; q_no++) {
503 : : otx2_vf_disable_iq(otx_ep, q_no);
504 : : otx2_vf_disable_oq(otx_ep, q_no);
505 : : }
506 : 0 : }
507 : :
508 : : static const struct otx_ep_config default_otx2_ep_conf = {
509 : : /* IQ attributes */
510 : : .iq = {
511 : : .max_iqs = OTX_EP_CFG_IO_QUEUES,
512 : : .instr_type = OTX_EP_32BYTE_INSTR,
513 : : .pending_list_size = (OTX_EP_MAX_IQ_DESCRIPTORS *
514 : : OTX_EP_CFG_IO_QUEUES),
515 : : },
516 : :
517 : : /* OQ attributes */
518 : : .oq = {
519 : : .max_oqs = OTX_EP_CFG_IO_QUEUES,
520 : : .info_ptr = OTX_EP_OQ_INFOPTR_MODE,
521 : : .refill_threshold = OTX_EP_OQ_REFIL_THRESHOLD,
522 : : },
523 : :
524 : : .num_iqdef_descs = OTX_EP_MAX_IQ_DESCRIPTORS,
525 : : .num_oqdef_descs = OTX_EP_MAX_OQ_DESCRIPTORS,
526 : : .oqdef_buf_size = OTX_EP_OQ_BUF_SIZE,
527 : : };
528 : :
529 : : static const struct otx_ep_config*
530 : : otx2_ep_get_defconf(struct otx_ep_device *otx_ep_dev __rte_unused)
531 : : {
532 : : const struct otx_ep_config *default_conf = NULL;
533 : :
534 : : default_conf = &default_otx2_ep_conf;
535 : :
536 : : return default_conf;
537 : : }
538 : :
539 : 0 : static int otx2_vf_enable_rxq_intr(struct otx_ep_device *otx_epvf,
540 : : uint16_t q_no)
541 : : {
542 : : union out_int_lvl_t out_int_lvl;
543 : : union out_cnts_t out_cnts;
544 : :
545 : 0 : out_int_lvl.d64 = otx2_read64(otx_epvf->hw_addr +
546 : : SDP_VF_R_OUT_INT_LEVELS(q_no));
547 : 0 : out_int_lvl.s.time_cnt_en = 1;
548 : 0 : out_int_lvl.s.cnt = 0;
549 : 0 : otx2_write64(out_int_lvl.d64, otx_epvf->hw_addr +
550 : : SDP_VF_R_OUT_INT_LEVELS(q_no));
551 : : out_cnts.d64 = 0;
552 : : out_cnts.s.resend = 1;
553 : 0 : otx2_write64(out_cnts.d64, otx_epvf->hw_addr + SDP_VF_R_OUT_CNTS(q_no));
554 : 0 : return 0;
555 : : }
556 : :
557 : 0 : static int otx2_vf_disable_rxq_intr(struct otx_ep_device *otx_epvf,
558 : : uint16_t q_no)
559 : : {
560 : : union out_int_lvl_t out_int_lvl;
561 : :
562 : : /* Disable the interrupt for this queue */
563 : 0 : out_int_lvl.d64 = otx2_read64(otx_epvf->hw_addr +
564 : : SDP_VF_R_OUT_INT_LEVELS(q_no));
565 : 0 : out_int_lvl.s.time_cnt_en = 0;
566 : 0 : out_int_lvl.s.cnt = 0;
567 : 0 : otx2_write64(out_int_lvl.d64, otx_epvf->hw_addr +
568 : : SDP_VF_R_OUT_INT_LEVELS(q_no));
569 : :
570 : 0 : return 0;
571 : : }
572 : :
573 : : int
574 : 0 : otx2_ep_vf_setup_device(struct otx_ep_device *otx_ep)
575 : : {
576 : : uint64_t reg_val = 0ull;
577 : :
578 : : /* If application doesn't provide its conf, use driver default conf */
579 [ # # ]: 0 : if (otx_ep->conf == NULL) {
580 : 0 : otx_ep->conf = otx2_ep_get_defconf(otx_ep);
581 : : if (otx_ep->conf == NULL) {
582 : : otx_ep_err("SDP VF default config not found");
583 : : return -ENOENT;
584 : : }
585 : 0 : otx_ep_info("Default config is used");
586 : : }
587 : :
588 : : /* Get IOQs (RPVF] count */
589 : 0 : reg_val = oct_ep_read64(otx_ep->hw_addr + SDP_VF_R_IN_CONTROL(0));
590 : :
591 : 0 : otx_ep->sriov_info.rings_per_vf = ((reg_val >> SDP_VF_R_IN_CTL_RPVF_POS)
592 : 0 : & SDP_VF_R_IN_CTL_RPVF_MASK);
593 : :
594 : 0 : otx_ep_info("SDP RPVF: %d", otx_ep->sriov_info.rings_per_vf);
595 : :
596 : 0 : otx_ep->fn_list.setup_iq_regs = otx2_vf_setup_iq_regs;
597 : 0 : otx_ep->fn_list.setup_oq_regs = otx2_vf_setup_oq_regs;
598 : :
599 : 0 : otx_ep->fn_list.setup_device_regs = otx2_vf_setup_device_regs;
600 : :
601 : 0 : otx_ep->fn_list.enable_io_queues = otx2_vf_enable_io_queues;
602 : 0 : otx_ep->fn_list.disable_io_queues = otx2_vf_disable_io_queues;
603 : :
604 : 0 : otx_ep->fn_list.enable_iq = otx2_vf_enable_iq;
605 : 0 : otx_ep->fn_list.disable_iq = otx2_vf_disable_iq;
606 : :
607 : 0 : otx_ep->fn_list.enable_oq = otx2_vf_enable_oq;
608 : 0 : otx_ep->fn_list.disable_oq = otx2_vf_disable_oq;
609 : :
610 : 0 : otx_ep->fn_list.enable_rxq_intr = otx2_vf_enable_rxq_intr;
611 : 0 : otx_ep->fn_list.disable_rxq_intr = otx2_vf_disable_rxq_intr;
612 : :
613 : : return 0;
614 : : }
|