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