xref: /dpdk/drivers/net/dpaa2/dpaa2_recycle.c (revision e77506397fc8005c5129e22e9e2d15d5876790fd)
1 /* * SPDX-License-Identifier: BSD-3-Clause
2  *
3  *   Copyright 2019-2021 NXP
4  *
5  */
6 
7 #include <time.h>
8 #include <net/if.h>
9 
10 #include <rte_mbuf.h>
11 #include <ethdev_driver.h>
12 #include <rte_malloc.h>
13 #include <rte_memcpy.h>
14 #include <rte_string_fns.h>
15 #include <rte_cycles.h>
16 #include <rte_kvargs.h>
17 #include <dev_driver.h>
18 #include <bus_fslmc_driver.h>
19 #include <rte_flow_driver.h>
20 
21 #include "dpaa2_pmd_logs.h"
22 #include <fslmc_vfio.h>
23 #include <dpaa2_hw_pvt.h>
24 #include <dpaa2_hw_mempool.h>
25 #include <dpaa2_hw_dpio.h>
26 #include <mc/fsl_dpmng.h>
27 #include "dpaa2_ethdev.h"
28 #include "dpaa2_sparser.h"
29 #include <fsl_qbman_debug.h>
30 
31 #include <rte_io.h>
32 #include <unistd.h>
33 #include <sys/mman.h>
34 
35 #ifndef PAGE_SIZE
36 #define PAGE_SIZE			(sysconf(_SC_PAGESIZE))
37 #endif
38 #define PAGE_MASK			(~(PAGE_SIZE - 1))
39 
40 #define LSX_SERDES_LAN_NB		8
41 #define LSX_SERDES_REG_BASE		0x1ea0000
42 #define LSX_LB_EN_BIT			0x10000000
43 
44 #define CONFIG_SYS_IMMR			0x01000000
45 
46 #define CONFIG_SYS_FSL_GUTS_ADDR	(CONFIG_SYS_IMMR + 0x00E00000)
47 #define CONFIG_SYS_FSL_SERDES_ADDR	(CONFIG_SYS_IMMR + 0xEA0000)
48 
49 #define FSL_LX_SRDS1_PRTCL_SHIFT	16
50 #define FSL_LX_SRDS2_PRTCL_SHIFT	21
51 #define FSL_LX_SRDS3_PRTCL_SHIFT	26
52 
53 #define FSL_LS_SRDS1_PRTCL_SHIFT	16
54 #define FSL_LS_SRDS2_PRTCL_SHIFT	0
55 
56 #define FSL_LX_SRDS1_REGSR		29
57 #define FSL_LX_SRDS2_REGSR		29
58 #define FSL_LX_SRDS3_REGSR		29
59 
60 #define FSL_LS_SRDS1_REGSR		29
61 #define FSL_LS_SRDS2_REGSR		30
62 
63 #define FSL_LX_SRDS1_PRTCL_MASK		0x001F0000
64 #define FSL_LX_SRDS2_PRTCL_MASK		0x03E00000
65 #define FSL_LX_SRDS3_PRTCL_MASK		0x7C000000
66 
67 #define FSL_LS_SRDS1_PRTCL_MASK		0xFFFF0000
68 #define FSL_LS_SRDS2_PRTCL_MASK		0x0000FFFF
69 
70 struct __rte_packed_begin ccsr_lx_serdes_lan {
71 	uint8_t unused1[0xa0];
72 	uint32_t lnatcsr0;
73 	uint8_t unused2[0x100 - 0xa4];
74 } __rte_packed_end;
75 
76 struct __rte_packed_begin ccsr_lx_serdes {
77 	uint8_t unused0[0x800];
78 	struct ccsr_lx_serdes_lan lane[LSX_SERDES_LAN_NB];
79 } __rte_packed_end;
80 
81 struct __rte_packed_begin ccsr_ls_serdes {
82 	uint8_t unused[0x800];
83 	struct serdes_lane {
84 		uint32_t gcr0;   /* General Control Register 0 */
85 		uint32_t gcr1;   /* General Control Register 1 */
86 		uint32_t gcr2;   /* General Control Register 2 */
87 		uint32_t ssc0;   /* Speed Switch Control 0 */
88 		uint32_t rec0;   /* Receive Equalization Control 0 */
89 		uint32_t rec1;   /* Receive Equalization Control 1 */
90 		uint32_t tec0;   /* Transmit Equalization Control 0 */
91 		uint32_t ssc1;   /* Speed Switch Control 1 */
92 		uint32_t ttlc;
93 		uint32_t rev[6];
94 		uint32_t tsc3;
95 	} lane[LSX_SERDES_LAN_NB];
96 	uint8_t res5[0x19fc - 0xa00];
97 } __rte_packed_end;
98 
99 struct __rte_packed_begin ccsr_gur {
100 	uint32_t	porsr1;		/* POR status 1 */
101 	uint32_t	porsr2;		/* POR status 2 */
102 	uint8_t	res_008[0x20 - 0x8];
103 	uint32_t	gpporcr1; /* General-purpose POR configuration */
104 	uint32_t	gpporcr2; /* General-purpose POR configuration 2 */
105 	uint32_t	gpporcr3;
106 	uint32_t	gpporcr4;
107 	uint8_t	res_030[0x60 - 0x30];
108 	uint32_t	dcfg_fusesr;	/* Fuse status register */
109 	uint8_t	res_064[0x70 - 0x64];
110 	uint32_t	devdisr;	/* Device disable control 1 */
111 	uint32_t	devdisr2;	/* Device disable control 2 */
112 	uint32_t	devdisr3;	/* Device disable control 3 */
113 	uint32_t	devdisr4;	/* Device disable control 4 */
114 	uint32_t	devdisr5;	/* Device disable control 5 */
115 	uint32_t	devdisr6;	/* Device disable control 6 */
116 	uint8_t	res_088[0x94 - 0x88];
117 	uint32_t	coredisr;	/* Device disable control 7 */
118 	uint8_t	res_098[0xa0 - 0x98];
119 	uint32_t	pvr;		/* Processor version */
120 	uint32_t	svr;		/* System version */
121 	uint8_t	res_0a8[0x100 - 0xa8];
122 	uint32_t	rcwsr[30];	/* Reset control word status */
123 
124 	uint8_t	res_178[0x200 - 0x178];
125 	uint32_t	scratchrw[16];	/* Scratch Read/Write */
126 	uint8_t	res_240[0x300 - 0x240];
127 	uint32_t	scratchw1r[4];	/* Scratch Read (Write once) */
128 	uint8_t	res_310[0x400 - 0x310];
129 	uint32_t	bootlocptrl; /* Boot location pointer low-order addr */
130 	uint32_t	bootlocptrh; /* Boot location pointer high-order addr */
131 	uint8_t	res_408[0x520 - 0x408];
132 	uint32_t	usb1_amqr;
133 	uint32_t	usb2_amqr;
134 	uint8_t	res_528[0x530 - 0x528];	/* add more registers when needed */
135 	uint32_t	sdmm1_amqr;
136 	uint32_t	sdmm2_amqr;
137 	uint8_t	res_538[0x550 - 0x538];	/* add more registers when needed */
138 	uint32_t	sata1_amqr;
139 	uint32_t	sata2_amqr;
140 	uint32_t	sata3_amqr;
141 	uint32_t	sata4_amqr;
142 	uint8_t	res_560[0x570 - 0x560];	/* add more registers when needed */
143 	uint32_t	misc1_amqr;
144 	uint8_t	res_574[0x590 - 0x574];	/* add more registers when needed */
145 	uint32_t	spare1_amqr;
146 	uint32_t	spare2_amqr;
147 	uint32_t	spare3_amqr;
148 	uint8_t	res_59c[0x620 - 0x59c];	/* add more registers when needed */
149 	uint32_t	gencr[7];	/* General Control Registers */
150 	uint8_t	res_63c[0x640 - 0x63c];	/* add more registers when needed */
151 	uint32_t	cgensr1;	/* Core General Status Register */
152 	uint8_t	res_644[0x660 - 0x644];	/* add more registers when needed */
153 	uint32_t	cgencr1;	/* Core General Control Register */
154 	uint8_t	res_664[0x740 - 0x664];	/* add more registers when needed */
155 	uint32_t	tp_ityp[64];	/* Topology Initiator Type Register */
156 	struct {
157 		uint32_t	upper;
158 		uint32_t	lower;
159 	} tp_cluster[4];	/* Core cluster n Topology Register */
160 	uint8_t	res_864[0x920 - 0x864];	/* add more registers when needed */
161 	uint32_t ioqoscr[8];	/*I/O Quality of Services Register */
162 	uint32_t uccr;
163 	uint8_t	res_944[0x960 - 0x944];	/* add more registers when needed */
164 	uint32_t ftmcr;
165 	uint8_t	res_964[0x990 - 0x964];	/* add more registers when needed */
166 	uint32_t coredisablesr;
167 	uint8_t	res_994[0xa00 - 0x994];	/* add more registers when needed */
168 	uint32_t sdbgcr; /*Secure Debug Configuration Register */
169 	uint8_t	res_a04[0xbf8 - 0xa04];	/* add more registers when needed */
170 	uint32_t ipbrr1;
171 	uint32_t ipbrr2;
172 	uint8_t	res_858[0x1000 - 0xc00];
173 } __rte_packed_end;
174 
175 static void *lsx_ccsr_map_region(uint64_t addr, size_t len)
176 {
177 	int fd;
178 	void *tmp;
179 	uint64_t start;
180 	uint64_t offset;
181 
182 	fd = open("/dev/mem", O_RDWR);
183 	if (fd < 0) {
184 		DPAA2_PMD_ERR("Fail to open /dev/mem");
185 		return NULL;
186 	}
187 
188 	start = addr & PAGE_MASK;
189 	offset = addr - start;
190 	len = len & PAGE_MASK;
191 	if (len < (size_t)PAGE_SIZE)
192 		len = PAGE_SIZE;
193 
194 	tmp = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start);
195 
196 	close(fd);
197 
198 	if (tmp != MAP_FAILED)
199 		return (uint8_t *)tmp + offset;
200 	else
201 		return NULL;
202 }
203 
204 static const uint8_t ls_sd1_prot_idx_map[] = {
205 	0x03, 0x05, 0x07, 0x09, 0x0a, 0x0c, 0x0e,
206 	0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c,
207 	0x1e, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a,
208 	0x2b, 0x2d, 0x2e, 0x30, 0x32, 0x33, 0x35,
209 	0x37, 0x39, 0x3b, 0x4b, 0x4c, 0x4d, 0x58
210 };
211 
212 static const uint8_t ls_sd2_prot_idx_map[] = {
213 	0x07, 0x09, 0x0a, 0x0c, 0x0e, 0x10, 0x12,
214 	0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x20,
215 	0x22, 0x24, 0x3d, 0x3f, 0x41, 0x43, 0x45,
216 	0x47, 0x49, 0x4f, 0x50, 0x51, 0x52, 0x53,
217 	0x54, 0x55, 0x56, 0x57
218 };
219 
220 static const uint8_t ls_sd1_eth_loopback_support[][LSX_SERDES_LAN_NB] = {
221 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x03*/
222 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 0x05*/
223 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x07*/
224 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x09*/
225 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x0a*/
226 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x0c*/
227 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x0e*/
228 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x10*/
229 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x12*/
230 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x14*/
231 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x16*/
232 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x18*/
233 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x1a*/
234 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x1c*/
235 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x1e*/
236 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x20*/
237 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x22*/
238 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x24*/
239 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x26*/
240 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x28*/
241 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x2a*/
242 
243 	{0, 0, 0, 0, 1, 1, 1, 1}, /* 0x2b*/
244 	{0, 0, 0, 0, 1, 1, 1, 1}, /* 0x2d*/
245 	{0, 0, 0, 0, 1, 1, 1, 1}, /* 0x2e*/
246 	{0, 0, 0, 0, 1, 1, 1, 1}, /* 0x30*/
247 
248 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x32*/
249 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x33*/
250 
251 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 0x35*/
252 	{1, 1, 0, 0, 0, 0, 0, 0}, /* 0x37*/
253 
254 	{0, 1, 1, 1, 0, 1, 1, 1}, /* 0x39*/
255 	{0, 1, 1, 1, 0, 1, 1, 1}, /* 0x3b*/
256 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 0x4b*/
257 	{0, 0, 0, 0, 1, 1, 1, 1}, /* 0x4c*/
258 	{0, 0, 1, 1, 0, 0, 1, 1}, /* 0x4d*/
259 	{0, 0, 0, 0, 0, 0, 1, 1}  /* 0x58*/
260 };
261 
262 static const uint8_t ls_sd2_eth_loopback_support[][LSX_SERDES_LAN_NB] = {
263 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x07*/
264 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x09*/
265 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x0a*/
266 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x0c*/
267 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x0e*/
268 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x10*/
269 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x12*/
270 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x14*/
271 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x16*/
272 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x18*/
273 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x1a*/
274 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x1c*/
275 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x1e*/
276 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x20*/
277 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x22*/
278 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x24*/
279 
280 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x3d*/
281 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x3f*/
282 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x41*/
283 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x43*/
284 
285 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 0x45*/
286 	{0, 1, 1, 1, 0, 1, 1, 1}, /* 0x47*/
287 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 0x49*/
288 
289 	{0, 0, 1, 1, 0, 0, 1, 1}, /* 0x4f*/
290 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x50*/
291 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x51*/
292 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 0x52*/
293 	{0, 1, 1, 1, 0, 1, 1, 1}, /* 0x53*/
294 	{0, 0, 1, 1, 0, 0, 1, 1}, /* 0x54*/
295 	{0, 1, 1, 1, 0, 1, 1, 1}, /* 0x55*/
296 	{0, 0, 1, 1, 0, 0, 1, 1}, /* 0x56*/
297 	{0, 0, 0, 0, 0, 0, 1, 1}  /* 0x57*/
298 };
299 
300 enum lsx_serdes_id {
301 	LSX_SERDES_1 = 1,
302 	LSX_SERDES_2 = 2
303 };
304 
305 static const uint8_t lx_sd1_loopback_support[][LSX_SERDES_LAN_NB] = {
306 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0 prot*/
307 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 1 prot*/
308 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 2 prot*/
309 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 3 prot*/
310 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 4 prot*/
311 	{0, 0, 0, 0, 1, 1, 1, 1}, /* 5 prot*/
312 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 6 prot*/
313 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 7 prot*/
314 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 8 prot*/
315 	{0, 1, 1, 1, 0, 1, 1, 1}, /* 9 prot*/
316 	{0, 1, 1, 1, 0, 1, 1, 1}, /* 10 prot*/
317 	{0, 0, 1, 1, 0, 0, 1, 1}, /* 11 prot*/
318 	{0, 0, 0, 0, 0, 0, 1, 1}, /* 12 prot*/
319 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 13 prot*/
320 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 14 prot*/
321 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 15 prot*/
322 	{0, 0, 1, 1, 0, 0, 0, 0}, /* 16 prot*/
323 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 17 prot*/
324 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 18 prot*/
325 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 19 prot*/
326 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 20 prot*/
327 	{1, 1, 1, 1, 0, 0, 1, 1}, /* 21 prot*/
328 	{1, 1, 1, 1, 0, 0, 1, 1}  /* 22 prot*/
329 };
330 
331 static const uint8_t lx_sd2_loopback_support[][LSX_SERDES_LAN_NB] = {
332 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0 prot*/
333 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 1 prot*/
334 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 2 prot*/
335 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 3 prot*/
336 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 4 prot*/
337 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 5 prot*/
338 	{0, 0, 0, 0, 1, 1, 1, 1}, /* 6 prot*/
339 	{0, 1, 1, 1, 0, 1, 1, 1}, /* 7 prot*/
340 	{0, 0, 0, 0, 0, 0, 1, 1}, /* 8 prot*/
341 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 9 prot*/
342 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 10 prot*/
343 	{0, 1, 1, 1, 0, 1, 1, 1}, /* 11 prot*/
344 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 12 prot*/
345 	{0, 0, 0, 0, 0, 0, 1, 1}, /* 13 prot*/
346 	{0, 0, 1, 1, 0, 0, 1, 1}  /* 14 prot*/
347 };
348 
349 static inline int
350 ls_mac_to_serdes_id(uint8_t mac_id)
351 {
352 	if (mac_id >= 1 && mac_id <= 8)
353 		return LSX_SERDES_1;
354 	if (mac_id >= 9 && mac_id <= 16)
355 		return LSX_SERDES_2;
356 
357 	return -1;
358 }
359 
360 static inline int
361 lx_mac_to_serdes_id(uint8_t mac_id)
362 {
363 	if (mac_id >= 1 && mac_id <= 10)
364 		return LSX_SERDES_1;
365 	if (mac_id >= 11 && mac_id <= 18)
366 		return LSX_SERDES_2;
367 
368 	return -1;
369 }
370 
371 static inline int
372 ls_serdes_cfg_to_idx(uint8_t sd_cfg, int sd_id)
373 {
374 	int i;
375 
376 	if (sd_id == LSX_SERDES_1) {
377 		for (i = 0; i < (int)sizeof(ls_sd1_prot_idx_map); i++) {
378 			if (ls_sd1_prot_idx_map[i] == sd_cfg)
379 				return i;
380 		}
381 	} else if (sd_id == LSX_SERDES_2) {
382 		for (i = 0; i < (int)sizeof(ls_sd2_prot_idx_map); i++) {
383 			if (ls_sd2_prot_idx_map[i] == sd_cfg)
384 				return i;
385 		}
386 	}
387 
388 	return -1;
389 }
390 
391 static inline int
392 lx_serdes_cfg_to_idx(uint8_t sd_cfg, int sd_id __rte_unused)
393 {
394 	return sd_cfg;
395 }
396 
397 static inline int
398 ls_mac_serdes_lpbk_support(uint16_t mac_id,
399 	uint16_t *serdes_id, uint16_t *lan_id)
400 {
401 	struct ccsr_gur *gur_base =
402 		lsx_ccsr_map_region(CONFIG_SYS_FSL_GUTS_ADDR,
403 			sizeof(struct ccsr_gur) / 64 * 64 + 64);
404 	uint32_t sd_cfg;
405 	int sd_id, sd_idx;
406 	uint16_t lan_id_tmp = 0;
407 	const uint8_t *ls_sd_loopback_support;
408 
409 	sd_id = ls_mac_to_serdes_id(mac_id);
410 
411 	if (sd_id == LSX_SERDES_1) {
412 		sd_cfg = rte_read32(&gur_base->rcwsr[FSL_LS_SRDS1_REGSR - 1]) &
413 				FSL_LS_SRDS1_PRTCL_MASK;
414 		sd_cfg >>= FSL_LS_SRDS1_PRTCL_SHIFT;
415 	} else if (sd_id == LSX_SERDES_2) {
416 		sd_cfg = rte_read32(&gur_base->rcwsr[FSL_LS_SRDS2_REGSR - 1]) &
417 				FSL_LS_SRDS2_PRTCL_MASK;
418 		sd_cfg >>= FSL_LS_SRDS2_PRTCL_SHIFT;
419 	} else {
420 		return false;
421 	}
422 	sd_cfg = sd_cfg & 0xff;
423 
424 	sd_idx = ls_serdes_cfg_to_idx(sd_cfg, sd_id);
425 	if (sd_idx < 0) {
426 		DPAA2_PMD_ERR("Serdes protocol(0x%02x) does not exist",
427 			sd_cfg);
428 		return false;
429 	}
430 
431 	if (sd_id == LSX_SERDES_1) {
432 		ls_sd_loopback_support =
433 			&ls_sd1_eth_loopback_support[sd_idx][0];
434 	} else {
435 		ls_sd_loopback_support =
436 			&ls_sd2_eth_loopback_support[sd_idx][0];
437 	}
438 
439 	if (sd_id == LSX_SERDES_1)
440 		lan_id_tmp = (mac_id - 1);
441 	else
442 		lan_id_tmp = (mac_id - 9);
443 
444 	if (lan_id_tmp >= LSX_SERDES_LAN_NB) {
445 		DPAA2_PMD_ERR("Invalid serdes lan(%d).", lan_id_tmp);
446 		return false;
447 	}
448 
449 	if (!ls_sd_loopback_support[lan_id_tmp])
450 		return false;
451 
452 	if (lan_id)
453 		*lan_id = lan_id_tmp;
454 	if (serdes_id)
455 		*serdes_id = sd_id;
456 
457 	return true;
458 }
459 
460 static inline int
461 lx_mac_serdes_lpbk_support(uint16_t mac_id,
462 	uint16_t *serdes_id, uint16_t *lan_id)
463 {
464 	struct ccsr_gur *gur_base =
465 		lsx_ccsr_map_region(CONFIG_SYS_FSL_GUTS_ADDR,
466 			sizeof(struct ccsr_gur) / 64 * 64 + 64);
467 	uint32_t sd_cfg;
468 	int sd_id, sd_idx;
469 	uint16_t lan_id_tmp = 0;
470 	const uint8_t *lx_sd_loopback_support;
471 
472 	sd_id = lx_mac_to_serdes_id(mac_id);
473 
474 	if (sd_id == LSX_SERDES_1) {
475 		sd_cfg = rte_read32(&gur_base->rcwsr[FSL_LX_SRDS1_REGSR - 1]) &
476 				FSL_LX_SRDS1_PRTCL_MASK;
477 		sd_cfg >>= FSL_LX_SRDS1_PRTCL_SHIFT;
478 	} else if (sd_id == LSX_SERDES_2) {
479 		sd_cfg = rte_read32(&gur_base->rcwsr[FSL_LX_SRDS2_REGSR - 1]) &
480 				FSL_LX_SRDS2_PRTCL_MASK;
481 		sd_cfg >>= FSL_LX_SRDS2_PRTCL_SHIFT;
482 	} else {
483 		return false;
484 	}
485 	sd_cfg = sd_cfg & 0xff;
486 
487 	sd_idx = lx_serdes_cfg_to_idx(sd_cfg, sd_id);
488 	if (sd_idx < 0)
489 		return false;
490 
491 	if (sd_id == LSX_SERDES_1)
492 		lx_sd_loopback_support = &lx_sd1_loopback_support[sd_idx][0];
493 	else
494 		lx_sd_loopback_support = &lx_sd2_loopback_support[sd_idx][0];
495 
496 	if (sd_id == LSX_SERDES_1) {
497 		if (mac_id == 1)
498 			lan_id_tmp = 0;
499 		else if (mac_id == 2)
500 			lan_id_tmp = 4;
501 		else
502 			lan_id_tmp = (mac_id - 3);
503 	} else {
504 		if (mac_id == 11)
505 			lan_id_tmp = 0;
506 		else if (mac_id == 12)
507 			lan_id_tmp = 1;
508 		else if (mac_id == 13)
509 			lan_id_tmp = 6;
510 		else if (mac_id == 14)
511 			lan_id_tmp = 7;
512 		else if (mac_id == 15)
513 			lan_id_tmp = 4;
514 		else if (mac_id == 16)
515 			lan_id_tmp = 5;
516 		else if (mac_id == 17)
517 			lan_id_tmp = 2;
518 		else if (mac_id == 18)
519 			lan_id_tmp = 3;
520 		else
521 			return false;
522 	}
523 
524 	if (lan_id_tmp >= LSX_SERDES_LAN_NB)
525 		return false;
526 
527 	if (!lx_sd_loopback_support[lan_id_tmp])
528 		return false;
529 
530 	if (lan_id)
531 		*lan_id = lan_id_tmp;
532 	if (serdes_id)
533 		*serdes_id = sd_id;
534 
535 	return true;
536 }
537 
538 static inline int
539 ls_serdes_eth_lpbk(uint16_t mac_id, int en)
540 {
541 	uint16_t serdes_id, lan_id;
542 	int ret;
543 	uint32_t data;
544 	struct ccsr_ls_serdes *serdes_base;
545 	void *reg = 0;
546 
547 	ret = ls_mac_serdes_lpbk_support(mac_id, &serdes_id, &lan_id);
548 	if (!ret)
549 		return -ENOTSUP;
550 
551 	serdes_base = lsx_ccsr_map_region(CONFIG_SYS_FSL_SERDES_ADDR +
552 				(serdes_id - LSX_SERDES_1) * 0x10000,
553 				sizeof(struct ccsr_ls_serdes) / 64 * 64 + 64);
554 	if (!serdes_base) {
555 		DPAA2_PMD_ERR("Serdes register map failed");
556 		return -ENOMEM;
557 	}
558 
559 	if (serdes_id == LSX_SERDES_1)
560 		lan_id = LSX_SERDES_LAN_NB - lan_id - 1;
561 
562 	reg = &serdes_base->lane[lan_id].tsc3;
563 
564 	data = rte_read32(reg);
565 	if (en)
566 		rte_write32(data | LSX_LB_EN_BIT, reg);
567 	else
568 		rte_write32(data & (~LSX_LB_EN_BIT), reg);
569 
570 	return 0;
571 }
572 
573 static inline int
574 lx_serdes_eth_lpbk(uint16_t mac_id, int en)
575 {
576 	uint16_t serdes_id = 0xffff, lan_id = 0xffff;
577 	int ret;
578 	uint32_t data;
579 	struct ccsr_lx_serdes *serdes_base;
580 	void *reg = 0;
581 
582 	ret = lx_mac_serdes_lpbk_support(mac_id, &serdes_id, &lan_id);
583 	if (!ret)
584 		return -ENOTSUP;
585 
586 	serdes_base = lsx_ccsr_map_region(CONFIG_SYS_FSL_SERDES_ADDR +
587 					(serdes_id - LSX_SERDES_1) * 0x10000,
588 					sizeof(struct ccsr_lx_serdes) / 64 * 64 + 64);
589 	if (!serdes_base) {
590 		DPAA2_PMD_ERR("Serdes register map failed");
591 		return -ENOMEM;
592 	}
593 
594 	if (serdes_id == LSX_SERDES_1)
595 		lan_id = LSX_SERDES_LAN_NB - lan_id - 1;
596 
597 	reg = &serdes_base->lane[lan_id].lnatcsr0;
598 
599 	data = rte_read32(reg);
600 	if (en)
601 		rte_write32(data | LSX_LB_EN_BIT, reg);
602 	else
603 		rte_write32(data & (~LSX_LB_EN_BIT), reg);
604 
605 	return 0;
606 }
607 
608 /* Configure dpaa2 port as recycle port */
609 int
610 dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev)
611 {
612 	struct rte_device *dev = eth_dev->device;
613 	struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
614 	struct rte_dpaa2_device *dpaa2_dev =
615 			container_of(dev, struct rte_dpaa2_device, device);
616 	struct fsl_mc_io *dpni_dev = eth_dev->process_private;
617 	struct dpni_port_cfg port_cfg;
618 	int ret;
619 
620 	if (priv->flags & DPAA2_TX_LOOPBACK_MODE) {
621 		DPAA2_PMD_INFO("%s has been configured recycle device.",
622 			eth_dev->data->name);
623 
624 		return 0;
625 	}
626 
627 	if (dpaa2_dev->ep_dev_type == DPAA2_MAC) {
628 		/** For dpmac-dpni connection,
629 		 * try setting serdes loopback as recycle device at first.
630 		 */
631 		if (dpaa2_svr_family == SVR_LS2088A) {
632 			ret = ls_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 1);
633 			if (!ret) {
634 				priv->flags |= DPAA2_TX_SERDES_LOOPBACK_MODE;
635 				return 0;
636 			}
637 		} else if (dpaa2_svr_family == SVR_LX2160A) {
638 			ret = lx_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 1);
639 			if (!ret) {
640 				priv->flags |= DPAA2_TX_SERDES_LOOPBACK_MODE;
641 				return 0;
642 			}
643 		} else {
644 			DPAA2_PMD_DEBUG("Serdes loopback not support SoC(0x%08x)",
645 				dpaa2_svr_family);
646 		}
647 
648 		/** If serdes loopback is not supported for this mac,
649 		 * trying set mac loopback.
650 		 */
651 
652 		port_cfg.loopback_en = 1;
653 		ret = dpni_set_port_cfg(dpni_dev, CMD_PRI_LOW,
654 				priv->token,
655 				DPNI_PORT_CFG_LOOPBACK,
656 				&port_cfg);
657 		if (ret) {
658 			DPAA2_PMD_ERR("Error(%d) to enable loopback", ret);
659 			return -ENOTSUP;
660 		}
661 
662 		priv->flags |= DPAA2_TX_MAC_LOOPBACK_MODE;
663 
664 		return 0;
665 	}
666 
667 	if (dpaa2_dev->ep_dev_type == DPAA2_ETH &&
668 		dpaa2_dev->object_id == dpaa2_dev->ep_object_id) {
669 		priv->flags |= DPAA2_TX_DPNI_LOOPBACK_MODE;
670 
671 		return 0;
672 	}
673 
674 	return -ENOTSUP;
675 }
676 
677 int
678 dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev)
679 {
680 	struct rte_device *dev = eth_dev->device;
681 	struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
682 	struct rte_dpaa2_device *dpaa2_dev =
683 			container_of(dev, struct rte_dpaa2_device, device);
684 	struct fsl_mc_io *dpni_dev = eth_dev->process_private;
685 	struct dpni_port_cfg port_cfg;
686 	int ret = 0;
687 
688 	if (!(priv->flags & DPAA2_TX_LOOPBACK_MODE))
689 		return 0;
690 
691 	if (priv->flags & DPAA2_TX_SERDES_LOOPBACK_MODE) {
692 		if (dpaa2_svr_family == SVR_LS2088A) {
693 			ret = ls_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 0);
694 			if (ret) {
695 				DPAA2_PMD_WARN("Error(%d) to disable Serdes loopback",
696 					ret);
697 			} else {
698 				priv->flags &= ~DPAA2_TX_SERDES_LOOPBACK_MODE;
699 			}
700 		} else if (dpaa2_svr_family == SVR_LX2160A) {
701 			ret = lx_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 0);
702 			if (ret) {
703 				DPAA2_PMD_WARN("Error(%d) to disable Serdes loopback",
704 					ret);
705 			} else {
706 				priv->flags &= ~DPAA2_TX_SERDES_LOOPBACK_MODE;
707 			}
708 		} else {
709 			DPAA2_PMD_DEBUG("Serdes loopback not support SoC(0x%08x)",
710 				dpaa2_svr_family);
711 		}
712 	}
713 
714 	if (priv->flags & DPAA2_TX_MAC_LOOPBACK_MODE) {
715 		port_cfg.loopback_en = 0;
716 		ret = dpni_set_port_cfg(dpni_dev, CMD_PRI_LOW,
717 				priv->token,
718 				DPNI_PORT_CFG_LOOPBACK,
719 				&port_cfg);
720 		if (ret) {
721 			DPAA2_PMD_ERR("Error(%d) to disable TX mac loopback",
722 				ret);
723 		} else {
724 			priv->flags &= ~DPAA2_TX_MAC_LOOPBACK_MODE;
725 		}
726 	}
727 
728 	if (priv->flags & DPAA2_TX_DPNI_LOOPBACK_MODE)
729 		priv->flags &= ~DPAA2_TX_DPNI_LOOPBACK_MODE;
730 
731 	return ret;
732 }
733 
734 int
735 dpaa2_dev_recycle_qp_setup(struct rte_dpaa2_device *dpaa2_dev,
736 	uint16_t qidx, uint64_t cntx,
737 	eth_rx_burst_t tx_lpbk, eth_tx_burst_t rx_lpbk,
738 	struct dpaa2_queue **txq,
739 	struct dpaa2_queue **rxq)
740 {
741 	struct rte_eth_dev *dev;
742 	struct rte_eth_dev_data *data;
743 	struct dpaa2_queue *txq_tmp;
744 	struct dpaa2_queue *rxq_tmp;
745 	struct dpaa2_dev_priv *priv;
746 
747 	dev = dpaa2_dev->eth_dev;
748 	data = dev->data;
749 	priv = data->dev_private;
750 
751 	if (!(priv->flags & DPAA2_TX_LOOPBACK_MODE) &&
752 		(tx_lpbk || rx_lpbk)) {
753 		DPAA2_PMD_ERR("%s is NOT recycle device!", data->name);
754 
755 		return -EINVAL;
756 	}
757 
758 	if (qidx >= data->nb_rx_queues || qidx >= data->nb_tx_queues)
759 		return -EINVAL;
760 
761 	rte_spinlock_lock(&priv->lpbk_qp_lock);
762 
763 	if (tx_lpbk)
764 		dev->tx_pkt_burst = tx_lpbk;
765 
766 	if (rx_lpbk)
767 		dev->rx_pkt_burst = rx_lpbk;
768 
769 	txq_tmp = data->tx_queues[qidx];
770 	txq_tmp->lpbk_cntx = cntx;
771 	rxq_tmp = data->rx_queues[qidx];
772 	rxq_tmp->lpbk_cntx = cntx;
773 
774 	if (txq)
775 		*txq = txq_tmp;
776 	if (rxq)
777 		*rxq = rxq_tmp;
778 
779 	rte_spinlock_unlock(&priv->lpbk_qp_lock);
780 
781 	return 0;
782 }
783