net/hns3: fix return value for unsupported tuple
[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 #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 ccsr_lx_serdes_lan {
71         uint8_t unused1[0xa0];
72         uint32_t lnatcsr0;
73         uint8_t unused2[0x100 - 0xa4];
74 } __rte_packed;
75
76 struct ccsr_lx_serdes {
77         uint8_t unused0[0x800];
78         struct ccsr_lx_serdes_lan lane[LSX_SERDES_LAN_NB];
79 } __rte_packed;
80
81 struct 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;
98
99 struct 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;
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\n",
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\n");
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\n");
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 }