xref: /dpdk/drivers/net/octeontx/base/octeontx_pkovf.c (revision cad78ca238180ff3601cea9fe58f36340176ff5e)
1445371e8SJerin Jacob /*
2445371e8SJerin Jacob  *   BSD LICENSE
3445371e8SJerin Jacob  *
4445371e8SJerin Jacob  *   Copyright (C) Cavium Inc. 2017. All rights reserved.
5445371e8SJerin Jacob  *
6445371e8SJerin Jacob  *   Redistribution and use in source and binary forms, with or without
7445371e8SJerin Jacob  *   modification, are permitted provided that the following conditions
8445371e8SJerin Jacob  *   are met:
9445371e8SJerin Jacob  *
10445371e8SJerin Jacob  *     * Redistributions of source code must retain the above copyright
11445371e8SJerin Jacob  *       notice, this list of conditions and the following disclaimer.
12445371e8SJerin Jacob  *     * Redistributions in binary form must reproduce the above copyright
13445371e8SJerin Jacob  *       notice, this list of conditions and the following disclaimer in
14445371e8SJerin Jacob  *       the documentation and/or other materials provided with the
15445371e8SJerin Jacob  *       distribution.
16445371e8SJerin Jacob  *     * Neither the name of Cavium networks nor the names of its
17445371e8SJerin Jacob  *       contributors may be used to endorse or promote products derived
18445371e8SJerin Jacob  *       from this software without specific prior written permission.
19445371e8SJerin Jacob  *
20445371e8SJerin Jacob  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21445371e8SJerin Jacob  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22445371e8SJerin Jacob  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23445371e8SJerin Jacob  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24445371e8SJerin Jacob  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25445371e8SJerin Jacob  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26445371e8SJerin Jacob  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27445371e8SJerin Jacob  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28445371e8SJerin Jacob  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29445371e8SJerin Jacob  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30445371e8SJerin Jacob  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31445371e8SJerin Jacob  */
32445371e8SJerin Jacob #include <stdbool.h>
33445371e8SJerin Jacob #include <string.h>
34445371e8SJerin Jacob #include <stdio.h>
35445371e8SJerin Jacob 
36445371e8SJerin Jacob #include <rte_eal.h>
37445371e8SJerin Jacob #include <rte_cycles.h>
38445371e8SJerin Jacob #include <rte_malloc.h>
39445371e8SJerin Jacob #include <rte_memory.h>
40445371e8SJerin Jacob #include <rte_pci.h>
41445371e8SJerin Jacob #include <rte_spinlock.h>
42445371e8SJerin Jacob 
43445371e8SJerin Jacob #include "../octeontx_logs.h"
44445371e8SJerin Jacob #include "octeontx_io.h"
45445371e8SJerin Jacob #include "octeontx_pkovf.h"
46445371e8SJerin Jacob 
47445371e8SJerin Jacob struct octeontx_pko_iomem {
48445371e8SJerin Jacob 	uint8_t		*va;
49445371e8SJerin Jacob 	phys_addr_t	iova;
50445371e8SJerin Jacob 	size_t		size;
51445371e8SJerin Jacob };
52445371e8SJerin Jacob 
53445371e8SJerin Jacob #define PKO_IOMEM_NULL (struct octeontx_pko_iomem){0, 0, 0}
54445371e8SJerin Jacob 
55445371e8SJerin Jacob struct octeontx_pko_fc_ctl_s {
56445371e8SJerin Jacob 	int64_t buf_cnt;
57445371e8SJerin Jacob 	int64_t padding[(PKO_DQ_FC_STRIDE / 8) - 1];
58445371e8SJerin Jacob };
59445371e8SJerin Jacob 
60445371e8SJerin Jacob struct octeontx_pkovf {
61445371e8SJerin Jacob 	uint8_t		*bar0;
62445371e8SJerin Jacob 	uint8_t		*bar2;
63445371e8SJerin Jacob 	uint16_t	domain;
64445371e8SJerin Jacob 	uint16_t	vfid;
65445371e8SJerin Jacob };
66445371e8SJerin Jacob 
67445371e8SJerin Jacob struct octeontx_pko_vf_ctl_s {
68445371e8SJerin Jacob 	rte_spinlock_t lock;
69445371e8SJerin Jacob 
70445371e8SJerin Jacob 	struct octeontx_pko_iomem fc_iomem;
71445371e8SJerin Jacob 	struct octeontx_pko_fc_ctl_s *fc_ctl;
72445371e8SJerin Jacob 	struct octeontx_pkovf pko[PKO_VF_MAX];
73445371e8SJerin Jacob 	struct {
74445371e8SJerin Jacob 		uint64_t chanid;
75445371e8SJerin Jacob 	} dq_map[PKO_VF_MAX * PKO_VF_NUM_DQ];
76445371e8SJerin Jacob };
77445371e8SJerin Jacob 
78445371e8SJerin Jacob static struct octeontx_pko_vf_ctl_s pko_vf_ctl;
79445371e8SJerin Jacob 
80*cad78ca2SJerin Jacob static void *
81*cad78ca2SJerin Jacob octeontx_pko_dq_vf_bar0(uint16_t txq)
82*cad78ca2SJerin Jacob {
83*cad78ca2SJerin Jacob 	int vf_ix;
84*cad78ca2SJerin Jacob 
85*cad78ca2SJerin Jacob 	vf_ix = txq / PKO_VF_NUM_DQ;
86*cad78ca2SJerin Jacob 	return pko_vf_ctl.pko[vf_ix].bar0;
87*cad78ca2SJerin Jacob }
88*cad78ca2SJerin Jacob 
89*cad78ca2SJerin Jacob static int
90*cad78ca2SJerin Jacob octeontx_pko_dq_gdq(uint16_t txq)
91*cad78ca2SJerin Jacob {
92*cad78ca2SJerin Jacob 	return txq % PKO_VF_NUM_DQ;
93*cad78ca2SJerin Jacob }
94*cad78ca2SJerin Jacob 
95*cad78ca2SJerin Jacob /**
96*cad78ca2SJerin Jacob  * Open a PKO DQ.
97*cad78ca2SJerin Jacob  */
98*cad78ca2SJerin Jacob static inline
99*cad78ca2SJerin Jacob int octeontx_pko_dq_open(uint16_t txq)
100*cad78ca2SJerin Jacob {
101*cad78ca2SJerin Jacob 	unsigned int reg_off;
102*cad78ca2SJerin Jacob 	uint8_t *vf_bar0;
103*cad78ca2SJerin Jacob 	uint64_t rtn;
104*cad78ca2SJerin Jacob 	int gdq;
105*cad78ca2SJerin Jacob 
106*cad78ca2SJerin Jacob 	vf_bar0 = octeontx_pko_dq_vf_bar0(txq);
107*cad78ca2SJerin Jacob 	gdq = octeontx_pko_dq_gdq(txq);
108*cad78ca2SJerin Jacob 
109*cad78ca2SJerin Jacob 	if (unlikely(gdq < 0 || vf_bar0 == NULL))
110*cad78ca2SJerin Jacob 		return -EINVAL;
111*cad78ca2SJerin Jacob 	*(volatile int64_t*)(pko_vf_ctl.fc_ctl + txq) =
112*cad78ca2SJerin Jacob 		PKO_DQ_FC_DEPTH_PAGES - PKO_DQ_FC_SKID;
113*cad78ca2SJerin Jacob 
114*cad78ca2SJerin Jacob 	rte_wmb();
115*cad78ca2SJerin Jacob 
116*cad78ca2SJerin Jacob 	octeontx_write64(PKO_DQ_FC_DEPTH_PAGES,
117*cad78ca2SJerin Jacob 			 vf_bar0 + PKO_VF_DQ_FC_STATUS(gdq));
118*cad78ca2SJerin Jacob 
119*cad78ca2SJerin Jacob 	/* Set the register to return descriptor (packet) count as DEPTH */
120*cad78ca2SJerin Jacob 	/* KIND=1, NCB_QUERY_RSP=0 */
121*cad78ca2SJerin Jacob 	octeontx_write64(1ull << PKO_DQ_KIND_BIT,
122*cad78ca2SJerin Jacob 				vf_bar0 + PKO_VF_DQ_WM_CTL(gdq));
123*cad78ca2SJerin Jacob 	reg_off = PKO_VF_DQ_OP_OPEN(gdq);
124*cad78ca2SJerin Jacob 
125*cad78ca2SJerin Jacob 	rtn = octeontx_reg_ldadd_u64(vf_bar0 + reg_off, 0);
126*cad78ca2SJerin Jacob 
127*cad78ca2SJerin Jacob 	/* PKO_DQOP_E::OPEN */
128*cad78ca2SJerin Jacob 	if (((rtn >> PKO_DQ_OP_BIT) & 0x3) != 0x1)
129*cad78ca2SJerin Jacob 		return -EIO;
130*cad78ca2SJerin Jacob 
131*cad78ca2SJerin Jacob 	switch (rtn >> PKO_DQ_STATUS_BIT) {
132*cad78ca2SJerin Jacob 	case 0xC:	/* DQALREADYCREATED */
133*cad78ca2SJerin Jacob 	case 0x0:	/* PASS */
134*cad78ca2SJerin Jacob 		break;
135*cad78ca2SJerin Jacob 	default:
136*cad78ca2SJerin Jacob 		return -EIO;
137*cad78ca2SJerin Jacob 	}
138*cad78ca2SJerin Jacob 
139*cad78ca2SJerin Jacob 	/* DRAIN=0, DRAIN_NULL_LINK=0, SW_XOFF=0 */
140*cad78ca2SJerin Jacob 	octeontx_write64(0, vf_bar0 + PKO_VF_DQ_SW_XOFF(gdq));
141*cad78ca2SJerin Jacob 
142*cad78ca2SJerin Jacob 	return rtn & ((1ull << PKO_DQ_OP_BIT) - 1);
143*cad78ca2SJerin Jacob }
144*cad78ca2SJerin Jacob 
145*cad78ca2SJerin Jacob /**
146*cad78ca2SJerin Jacob  * Close a PKO DQ
147*cad78ca2SJerin Jacob  * Flush all packets pending.
148*cad78ca2SJerin Jacob  */
149*cad78ca2SJerin Jacob static inline
150*cad78ca2SJerin Jacob int octeontx_pko_dq_close(uint16_t txq)
151*cad78ca2SJerin Jacob {
152*cad78ca2SJerin Jacob 	unsigned int reg_off;
153*cad78ca2SJerin Jacob 	uint8_t *vf_bar0;
154*cad78ca2SJerin Jacob 	uint64_t rtn;
155*cad78ca2SJerin Jacob 	int res;
156*cad78ca2SJerin Jacob 
157*cad78ca2SJerin Jacob 	vf_bar0 = octeontx_pko_dq_vf_bar0(txq);
158*cad78ca2SJerin Jacob 	res = octeontx_pko_dq_gdq(txq);
159*cad78ca2SJerin Jacob 
160*cad78ca2SJerin Jacob 	if (unlikely(res < 0 || vf_bar0 == NULL))
161*cad78ca2SJerin Jacob 		return -EINVAL;
162*cad78ca2SJerin Jacob 
163*cad78ca2SJerin Jacob 	reg_off = PKO_VF_DQ_OP_CLOSE(res);
164*cad78ca2SJerin Jacob 
165*cad78ca2SJerin Jacob 	rtn = octeontx_reg_ldadd_u64(vf_bar0 + reg_off, 0);
166*cad78ca2SJerin Jacob 
167*cad78ca2SJerin Jacob 	/* PKO_DQOP_E::CLOSE */
168*cad78ca2SJerin Jacob 	if (((rtn >> PKO_DQ_OP_BIT) & 0x3) != 0x2)
169*cad78ca2SJerin Jacob 		return -EIO;
170*cad78ca2SJerin Jacob 
171*cad78ca2SJerin Jacob 	switch (rtn >> PKO_DQ_STATUS_BIT) {
172*cad78ca2SJerin Jacob 	case 0xD:	/* DQNOTCREATED */
173*cad78ca2SJerin Jacob 	case 0x0:	/* PASS */
174*cad78ca2SJerin Jacob 		break;
175*cad78ca2SJerin Jacob 	default:
176*cad78ca2SJerin Jacob 		return -EIO;
177*cad78ca2SJerin Jacob 	}
178*cad78ca2SJerin Jacob 
179*cad78ca2SJerin Jacob 	res = rtn & ((1ull << PKO_DQ_OP_BIT) - 1); /* DEPTH */
180*cad78ca2SJerin Jacob 	return res;
181*cad78ca2SJerin Jacob }
182*cad78ca2SJerin Jacob 
183*cad78ca2SJerin Jacob /* Flush all packets pending on a DQ */
184*cad78ca2SJerin Jacob static inline
185*cad78ca2SJerin Jacob int octeontx_pko_dq_drain(uint16_t txq)
186*cad78ca2SJerin Jacob {
187*cad78ca2SJerin Jacob 	unsigned int gdq;
188*cad78ca2SJerin Jacob 	uint8_t *vf_bar0;
189*cad78ca2SJerin Jacob 	uint64_t reg;
190*cad78ca2SJerin Jacob 	int res, timo = PKO_DQ_DRAIN_TO;
191*cad78ca2SJerin Jacob 
192*cad78ca2SJerin Jacob 	vf_bar0 = octeontx_pko_dq_vf_bar0(txq);
193*cad78ca2SJerin Jacob 	res = octeontx_pko_dq_gdq(txq);
194*cad78ca2SJerin Jacob 	gdq = res;
195*cad78ca2SJerin Jacob 
196*cad78ca2SJerin Jacob 	 /* DRAIN=1, DRAIN_NULL_LINK=0, SW_XOFF=1 */
197*cad78ca2SJerin Jacob 	 octeontx_write64(0x3, vf_bar0 + PKO_VF_DQ_SW_XOFF(gdq));
198*cad78ca2SJerin Jacob 	/* Wait until buffers leave DQs */
199*cad78ca2SJerin Jacob 	reg = octeontx_read64(vf_bar0 + PKO_VF_DQ_WM_CNT(gdq));
200*cad78ca2SJerin Jacob 	while (reg && timo > 0) {
201*cad78ca2SJerin Jacob 		rte_delay_us(100);
202*cad78ca2SJerin Jacob 		timo--;
203*cad78ca2SJerin Jacob 		reg = octeontx_read64(vf_bar0 + PKO_VF_DQ_WM_CNT(gdq));
204*cad78ca2SJerin Jacob 	}
205*cad78ca2SJerin Jacob 	/* DRAIN=0, DRAIN_NULL_LINK=0, SW_XOFF=0 */
206*cad78ca2SJerin Jacob 	octeontx_write64(0, vf_bar0 + PKO_VF_DQ_SW_XOFF(gdq));
207*cad78ca2SJerin Jacob 
208*cad78ca2SJerin Jacob 	return reg;
209*cad78ca2SJerin Jacob }
210*cad78ca2SJerin Jacob 
211*cad78ca2SJerin Jacob static inline int
212*cad78ca2SJerin Jacob octeontx_pko_dq_range_lookup(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid,
213*cad78ca2SJerin Jacob 			     unsigned int dq_num, unsigned int dq_from)
214*cad78ca2SJerin Jacob {
215*cad78ca2SJerin Jacob 	unsigned int dq, dq_cnt;
216*cad78ca2SJerin Jacob 	unsigned int dq_base;
217*cad78ca2SJerin Jacob 
218*cad78ca2SJerin Jacob 	dq_cnt = 0;
219*cad78ca2SJerin Jacob 	dq = dq_from;
220*cad78ca2SJerin Jacob 	while (dq < RTE_DIM(ctl->dq_map)) {
221*cad78ca2SJerin Jacob 		dq_base = dq;
222*cad78ca2SJerin Jacob 		dq_cnt = 0;
223*cad78ca2SJerin Jacob 		while (ctl->dq_map[dq].chanid == ~chanid &&
224*cad78ca2SJerin Jacob 			dq < RTE_DIM(ctl->dq_map)) {
225*cad78ca2SJerin Jacob 			dq_cnt++;
226*cad78ca2SJerin Jacob 			if (dq_cnt == dq_num)
227*cad78ca2SJerin Jacob 				return dq_base;
228*cad78ca2SJerin Jacob 			dq++;
229*cad78ca2SJerin Jacob 		}
230*cad78ca2SJerin Jacob 		dq++;
231*cad78ca2SJerin Jacob 	}
232*cad78ca2SJerin Jacob 	return -1;
233*cad78ca2SJerin Jacob }
234*cad78ca2SJerin Jacob 
235*cad78ca2SJerin Jacob static inline void
236*cad78ca2SJerin Jacob octeontx_pko_dq_range_assign(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid,
237*cad78ca2SJerin Jacob 			     unsigned int dq_base, unsigned int dq_num)
238*cad78ca2SJerin Jacob {
239*cad78ca2SJerin Jacob 	unsigned int dq, dq_cnt;
240*cad78ca2SJerin Jacob 
241*cad78ca2SJerin Jacob 	dq_cnt = 0;
242*cad78ca2SJerin Jacob 	while (dq_cnt < dq_num) {
243*cad78ca2SJerin Jacob 		dq = dq_base + dq_cnt;
244*cad78ca2SJerin Jacob 
245*cad78ca2SJerin Jacob 		octeontx_log_dbg("DQ# %u assigned to CHAN# %" PRIx64 "", dq,
246*cad78ca2SJerin Jacob 			chanid);
247*cad78ca2SJerin Jacob 
248*cad78ca2SJerin Jacob 		ctl->dq_map[dq].chanid = ~chanid;
249*cad78ca2SJerin Jacob 		dq_cnt++;
250*cad78ca2SJerin Jacob 	}
251*cad78ca2SJerin Jacob }
252*cad78ca2SJerin Jacob 
253*cad78ca2SJerin Jacob static inline int
254*cad78ca2SJerin Jacob octeontx_pko_dq_claim(struct octeontx_pko_vf_ctl_s *ctl, unsigned int dq_base,
255*cad78ca2SJerin Jacob 		      unsigned int dq_num, uint64_t chanid)
256*cad78ca2SJerin Jacob {
257*cad78ca2SJerin Jacob 	const uint64_t null_chanid = ~0ull;
258*cad78ca2SJerin Jacob 	int dq;
259*cad78ca2SJerin Jacob 
260*cad78ca2SJerin Jacob 	rte_spinlock_lock(&ctl->lock);
261*cad78ca2SJerin Jacob 
262*cad78ca2SJerin Jacob 	dq = octeontx_pko_dq_range_lookup(ctl, null_chanid, dq_num, dq_base);
263*cad78ca2SJerin Jacob 	if (dq < 0 || (unsigned int)dq != dq_base) {
264*cad78ca2SJerin Jacob 		rte_spinlock_unlock(&ctl->lock);
265*cad78ca2SJerin Jacob 		return -1;
266*cad78ca2SJerin Jacob 	}
267*cad78ca2SJerin Jacob 	octeontx_pko_dq_range_assign(ctl, chanid, dq_base, dq_num);
268*cad78ca2SJerin Jacob 
269*cad78ca2SJerin Jacob 	rte_spinlock_unlock(&ctl->lock);
270*cad78ca2SJerin Jacob 
271*cad78ca2SJerin Jacob 	return 0;
272*cad78ca2SJerin Jacob }
273*cad78ca2SJerin Jacob 
274*cad78ca2SJerin Jacob static inline int
275*cad78ca2SJerin Jacob octeontx_pko_dq_free(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid)
276*cad78ca2SJerin Jacob {
277*cad78ca2SJerin Jacob 	const uint64_t null_chanid = ~0ull;
278*cad78ca2SJerin Jacob 	unsigned int dq = 0, dq_cnt = 0;
279*cad78ca2SJerin Jacob 
280*cad78ca2SJerin Jacob 	rte_spinlock_lock(&ctl->lock);
281*cad78ca2SJerin Jacob 	while (dq < RTE_DIM(ctl->dq_map)) {
282*cad78ca2SJerin Jacob 		if (ctl->dq_map[dq].chanid == ~chanid) {
283*cad78ca2SJerin Jacob 			ctl->dq_map[dq].chanid = ~null_chanid;
284*cad78ca2SJerin Jacob 			dq_cnt++;
285*cad78ca2SJerin Jacob 		}
286*cad78ca2SJerin Jacob 		dq++;
287*cad78ca2SJerin Jacob 	}
288*cad78ca2SJerin Jacob 	rte_spinlock_unlock(&ctl->lock);
289*cad78ca2SJerin Jacob 
290*cad78ca2SJerin Jacob 	return dq_cnt > 0 ? 0 : -EINVAL;
291*cad78ca2SJerin Jacob }
292*cad78ca2SJerin Jacob 
293*cad78ca2SJerin Jacob int
294*cad78ca2SJerin Jacob octeontx_pko_channel_open(int dq_base, int dq_num, int chanid)
295*cad78ca2SJerin Jacob {
296*cad78ca2SJerin Jacob 	struct octeontx_pko_vf_ctl_s *ctl = &pko_vf_ctl;
297*cad78ca2SJerin Jacob 	int res;
298*cad78ca2SJerin Jacob 
299*cad78ca2SJerin Jacob 	res = octeontx_pko_dq_claim(ctl, dq_base, dq_num, chanid);
300*cad78ca2SJerin Jacob 	if (res < 0)
301*cad78ca2SJerin Jacob 		return -1;
302*cad78ca2SJerin Jacob 
303*cad78ca2SJerin Jacob 	return 0;
304*cad78ca2SJerin Jacob }
305*cad78ca2SJerin Jacob 
306*cad78ca2SJerin Jacob int
307*cad78ca2SJerin Jacob octeontx_pko_channel_close(int chanid)
308*cad78ca2SJerin Jacob {
309*cad78ca2SJerin Jacob 	struct octeontx_pko_vf_ctl_s *ctl = &pko_vf_ctl;
310*cad78ca2SJerin Jacob 	int res;
311*cad78ca2SJerin Jacob 
312*cad78ca2SJerin Jacob 	res = octeontx_pko_dq_free(ctl, chanid);
313*cad78ca2SJerin Jacob 	if (res < 0)
314*cad78ca2SJerin Jacob 		return -1;
315*cad78ca2SJerin Jacob 
316*cad78ca2SJerin Jacob 	return 0;
317*cad78ca2SJerin Jacob }
318*cad78ca2SJerin Jacob 
319*cad78ca2SJerin Jacob static inline int
320*cad78ca2SJerin Jacob octeontx_pko_chan_start(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid)
321*cad78ca2SJerin Jacob {
322*cad78ca2SJerin Jacob 	unsigned int dq_vf;
323*cad78ca2SJerin Jacob 	unsigned int dq, dq_cnt;
324*cad78ca2SJerin Jacob 
325*cad78ca2SJerin Jacob 	dq_cnt = 0;
326*cad78ca2SJerin Jacob 	dq = 0;
327*cad78ca2SJerin Jacob 	while (dq < RTE_DIM(ctl->dq_map)) {
328*cad78ca2SJerin Jacob 		dq_vf = dq / PKO_VF_NUM_DQ;
329*cad78ca2SJerin Jacob 
330*cad78ca2SJerin Jacob 		if (!ctl->pko[dq_vf].bar0) {
331*cad78ca2SJerin Jacob 			dq += PKO_VF_NUM_DQ;
332*cad78ca2SJerin Jacob 			continue;
333*cad78ca2SJerin Jacob 		}
334*cad78ca2SJerin Jacob 
335*cad78ca2SJerin Jacob 		if (ctl->dq_map[dq].chanid != ~chanid) {
336*cad78ca2SJerin Jacob 			dq++;
337*cad78ca2SJerin Jacob 			continue;
338*cad78ca2SJerin Jacob 		}
339*cad78ca2SJerin Jacob 
340*cad78ca2SJerin Jacob 		if (octeontx_pko_dq_open(dq) < 0)
341*cad78ca2SJerin Jacob 			break;
342*cad78ca2SJerin Jacob 
343*cad78ca2SJerin Jacob 		dq_cnt++;
344*cad78ca2SJerin Jacob 		dq++;
345*cad78ca2SJerin Jacob 	}
346*cad78ca2SJerin Jacob 
347*cad78ca2SJerin Jacob 	return dq_cnt;
348*cad78ca2SJerin Jacob }
349*cad78ca2SJerin Jacob 
350*cad78ca2SJerin Jacob int
351*cad78ca2SJerin Jacob octeontx_pko_channel_start(int chanid)
352*cad78ca2SJerin Jacob {
353*cad78ca2SJerin Jacob 	struct octeontx_pko_vf_ctl_s *ctl = &pko_vf_ctl;
354*cad78ca2SJerin Jacob 	int dq_cnt;
355*cad78ca2SJerin Jacob 
356*cad78ca2SJerin Jacob 	dq_cnt = octeontx_pko_chan_start(ctl, chanid);
357*cad78ca2SJerin Jacob 	if (dq_cnt < 0)
358*cad78ca2SJerin Jacob 		return -1;
359*cad78ca2SJerin Jacob 
360*cad78ca2SJerin Jacob 	return dq_cnt;
361*cad78ca2SJerin Jacob }
362*cad78ca2SJerin Jacob 
363*cad78ca2SJerin Jacob static inline int
364*cad78ca2SJerin Jacob octeontx_pko_chan_stop(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid)
365*cad78ca2SJerin Jacob {
366*cad78ca2SJerin Jacob 	unsigned int dq, dq_cnt, dq_vf;
367*cad78ca2SJerin Jacob 	int res;
368*cad78ca2SJerin Jacob 
369*cad78ca2SJerin Jacob 	dq_cnt = 0;
370*cad78ca2SJerin Jacob 	dq = 0;
371*cad78ca2SJerin Jacob 	while (dq < RTE_DIM(ctl->dq_map)) {
372*cad78ca2SJerin Jacob 		dq_vf = dq / PKO_VF_NUM_DQ;
373*cad78ca2SJerin Jacob 
374*cad78ca2SJerin Jacob 		if (!ctl->pko[dq_vf].bar0) {
375*cad78ca2SJerin Jacob 			dq += PKO_VF_NUM_DQ;
376*cad78ca2SJerin Jacob 			continue;
377*cad78ca2SJerin Jacob 		}
378*cad78ca2SJerin Jacob 
379*cad78ca2SJerin Jacob 		if (ctl->dq_map[dq].chanid != ~chanid) {
380*cad78ca2SJerin Jacob 			dq++;
381*cad78ca2SJerin Jacob 			continue;
382*cad78ca2SJerin Jacob 		}
383*cad78ca2SJerin Jacob 
384*cad78ca2SJerin Jacob 		res = octeontx_pko_dq_drain(dq);
385*cad78ca2SJerin Jacob 		if (res > 0)
386*cad78ca2SJerin Jacob 			octeontx_log_err("draining DQ%d, buffers left: %x",
387*cad78ca2SJerin Jacob 					 dq, res);
388*cad78ca2SJerin Jacob 
389*cad78ca2SJerin Jacob 		res = octeontx_pko_dq_close(dq);
390*cad78ca2SJerin Jacob 		if (res < 0)
391*cad78ca2SJerin Jacob 			octeontx_log_err("closing DQ%d failed\n", dq);
392*cad78ca2SJerin Jacob 
393*cad78ca2SJerin Jacob 		dq_cnt++;
394*cad78ca2SJerin Jacob 		dq++;
395*cad78ca2SJerin Jacob 	}
396*cad78ca2SJerin Jacob 	return dq_cnt;
397*cad78ca2SJerin Jacob }
398*cad78ca2SJerin Jacob 
399*cad78ca2SJerin Jacob int
400*cad78ca2SJerin Jacob octeontx_pko_channel_stop(int chanid)
401*cad78ca2SJerin Jacob {
402*cad78ca2SJerin Jacob 	struct octeontx_pko_vf_ctl_s *ctl = &pko_vf_ctl;
403*cad78ca2SJerin Jacob 
404*cad78ca2SJerin Jacob 	octeontx_pko_chan_stop(ctl, chanid);
405*cad78ca2SJerin Jacob 	return 0;
406*cad78ca2SJerin Jacob }
407*cad78ca2SJerin Jacob 
408445371e8SJerin Jacob static void
409445371e8SJerin Jacob octeontx_pkovf_setup(void)
410445371e8SJerin Jacob {
411445371e8SJerin Jacob 	static bool init_once;
412445371e8SJerin Jacob 
413445371e8SJerin Jacob 	if (!init_once) {
414445371e8SJerin Jacob 		unsigned int i;
415445371e8SJerin Jacob 
416445371e8SJerin Jacob 		rte_spinlock_init(&pko_vf_ctl.lock);
417445371e8SJerin Jacob 
418445371e8SJerin Jacob 		pko_vf_ctl.fc_iomem = PKO_IOMEM_NULL;
419445371e8SJerin Jacob 		pko_vf_ctl.fc_ctl = NULL;
420445371e8SJerin Jacob 
421445371e8SJerin Jacob 		for (i = 0; i < PKO_VF_MAX; i++) {
422445371e8SJerin Jacob 			pko_vf_ctl.pko[i].bar0 = NULL;
423445371e8SJerin Jacob 			pko_vf_ctl.pko[i].bar2 = NULL;
424445371e8SJerin Jacob 			pko_vf_ctl.pko[i].domain = ~(uint16_t)0;
425445371e8SJerin Jacob 			pko_vf_ctl.pko[i].vfid = ~(uint16_t)0;
426445371e8SJerin Jacob 		}
427445371e8SJerin Jacob 
428445371e8SJerin Jacob 		for (i = 0; i < (PKO_VF_MAX * PKO_VF_NUM_DQ); i++)
429445371e8SJerin Jacob 			pko_vf_ctl.dq_map[i].chanid = 0;
430445371e8SJerin Jacob 
431445371e8SJerin Jacob 		init_once = true;
432445371e8SJerin Jacob 	}
433445371e8SJerin Jacob }
434445371e8SJerin Jacob 
435445371e8SJerin Jacob /* PKOVF pcie device*/
436445371e8SJerin Jacob static int
437445371e8SJerin Jacob pkovf_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
438445371e8SJerin Jacob {
439445371e8SJerin Jacob 	uint64_t val;
440445371e8SJerin Jacob 	uint16_t vfid;
441445371e8SJerin Jacob 	uint16_t domain;
442445371e8SJerin Jacob 	uint8_t *bar0;
443445371e8SJerin Jacob 	uint8_t *bar2;
444445371e8SJerin Jacob 	struct octeontx_pkovf *res;
445445371e8SJerin Jacob 
446445371e8SJerin Jacob 	RTE_SET_USED(pci_drv);
447445371e8SJerin Jacob 
448445371e8SJerin Jacob 	/* For secondary processes, the primary has done all the work */
449445371e8SJerin Jacob 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
450445371e8SJerin Jacob 		return 0;
451445371e8SJerin Jacob 
452445371e8SJerin Jacob 	if (pci_dev->mem_resource[0].addr == NULL ||
453445371e8SJerin Jacob 	    pci_dev->mem_resource[2].addr == NULL) {
454445371e8SJerin Jacob 		octeontx_log_err("Empty bars %p %p",
455445371e8SJerin Jacob 			pci_dev->mem_resource[0].addr,
456445371e8SJerin Jacob 			pci_dev->mem_resource[2].addr);
457445371e8SJerin Jacob 		return -ENODEV;
458445371e8SJerin Jacob 	}
459445371e8SJerin Jacob 	bar0 = pci_dev->mem_resource[0].addr;
460445371e8SJerin Jacob 	bar2 = pci_dev->mem_resource[2].addr;
461445371e8SJerin Jacob 
462445371e8SJerin Jacob 	octeontx_pkovf_setup();
463445371e8SJerin Jacob 
464445371e8SJerin Jacob 	/* get vfid and domain */
465445371e8SJerin Jacob 	val = octeontx_read64(bar0 + PKO_VF_DQ_FC_CONFIG);
466445371e8SJerin Jacob 	domain = (val >> 7) & 0xffff;
467445371e8SJerin Jacob 	vfid = (val >> 23) & 0xffff;
468445371e8SJerin Jacob 
469445371e8SJerin Jacob 	if (unlikely(vfid >= PKO_VF_MAX)) {
470445371e8SJerin Jacob 		octeontx_log_err("pko: Invalid vfid %d", vfid);
471445371e8SJerin Jacob 		return -EINVAL;
472445371e8SJerin Jacob 	}
473445371e8SJerin Jacob 
474445371e8SJerin Jacob 	res = &pko_vf_ctl.pko[vfid];
475445371e8SJerin Jacob 	res->vfid = vfid;
476445371e8SJerin Jacob 	res->domain = domain;
477445371e8SJerin Jacob 	res->bar0 = bar0;
478445371e8SJerin Jacob 	res->bar2 = bar2;
479445371e8SJerin Jacob 
480445371e8SJerin Jacob 	octeontx_log_dbg("Domain=%d group=%d", res->domain, res->vfid);
481445371e8SJerin Jacob 	return 0;
482445371e8SJerin Jacob }
483445371e8SJerin Jacob 
484445371e8SJerin Jacob #define PCI_VENDOR_ID_CAVIUM               0x177D
485445371e8SJerin Jacob #define PCI_DEVICE_ID_OCTEONTX_PKO_VF      0xA049
486445371e8SJerin Jacob 
487445371e8SJerin Jacob static const struct rte_pci_id pci_pkovf_map[] = {
488445371e8SJerin Jacob 	{
489445371e8SJerin Jacob 		RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM,
490445371e8SJerin Jacob 				PCI_DEVICE_ID_OCTEONTX_PKO_VF)
491445371e8SJerin Jacob 	},
492445371e8SJerin Jacob 	{
493445371e8SJerin Jacob 		.vendor_id = 0,
494445371e8SJerin Jacob 	},
495445371e8SJerin Jacob };
496445371e8SJerin Jacob 
497445371e8SJerin Jacob static struct rte_pci_driver pci_pkovf = {
498445371e8SJerin Jacob 	.id_table = pci_pkovf_map,
499445371e8SJerin Jacob 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
500445371e8SJerin Jacob 	.probe = pkovf_probe,
501445371e8SJerin Jacob };
502445371e8SJerin Jacob 
503445371e8SJerin Jacob RTE_PMD_REGISTER_PCI(octeontx_pkovf, pci_pkovf);
504