1// SPDX-License-Identifier: GPL-2.0-or-later
2/* Applied Micro X-Gene SoC Ethernet Classifier structures
3 *
4 * Copyright (c) 2016, Applied Micro Circuits Corporation
5 * Authors: Khuong Dinh <kdinh@apm.com>
6 * Tanmay Inamdar <tinamdar@apm.com>
7 * Iyappan Subramanian <isubramanian@apm.com>
8 */
9
10#include "xgene_enet_main.h"
11
12/* interfaces to convert structures to HW recognized bit formats */
13static void xgene_cle_sband_to_hw(u8 frag, enum xgene_cle_prot_version ver,
14 enum xgene_cle_prot_type type, u32 len,
15 u32 *reg)
16{
17 *reg = SET_VAL(SB_IPFRAG, frag) |
18 SET_VAL(SB_IPPROT, type) |
19 SET_VAL(SB_IPVER, ver) |
20 SET_VAL(SB_HDRLEN, len);
21}
22
23static void xgene_cle_idt_to_hw(struct xgene_enet_pdata *pdata,
24 u32 dstqid, u32 fpsel,
25 u32 nfpsel, u32 *idt_reg)
26{
27 if (pdata->enet_id == XGENE_ENET1) {
28 *idt_reg = SET_VAL(IDT_DSTQID, dstqid) |
29 SET_VAL(IDT_FPSEL1, fpsel) |
30 SET_VAL(IDT_NFPSEL1, nfpsel);
31 } else {
32 *idt_reg = SET_VAL(IDT_DSTQID, dstqid) |
33 SET_VAL(IDT_FPSEL, fpsel) |
34 SET_VAL(IDT_NFPSEL, nfpsel);
35 }
36}
37
38static void xgene_cle_dbptr_to_hw(struct xgene_enet_pdata *pdata,
39 struct xgene_cle_dbptr *dbptr, u32 *buf)
40{
41 buf[0] = SET_VAL(CLE_DROP, dbptr->drop);
42 buf[4] = SET_VAL(CLE_FPSEL, dbptr->fpsel) |
43 SET_VAL(CLE_NFPSEL, dbptr->nxtfpsel) |
44 SET_VAL(CLE_DSTQIDL, dbptr->dstqid);
45
46 buf[5] = SET_VAL(CLE_DSTQIDH, (u32)dbptr->dstqid >> CLE_DSTQIDL_LEN) |
47 SET_VAL(CLE_PRIORITY, dbptr->cle_priority);
48}
49
50static void xgene_cle_kn_to_hw(struct xgene_cle_ptree_kn *kn, u32 *buf)
51{
52 u32 i, j = 0;
53 u32 data;
54
55 buf[j++] = SET_VAL(CLE_TYPE, kn->node_type);
56 for (i = 0; i < kn->num_keys; i++) {
57 struct xgene_cle_ptree_key *key = &kn->key[i];
58
59 if (!(i % 2)) {
60 buf[j] = SET_VAL(CLE_KN_PRIO, key->priority) |
61 SET_VAL(CLE_KN_RPTR, key->result_pointer);
62 } else {
63 data = SET_VAL(CLE_KN_PRIO, key->priority) |
64 SET_VAL(CLE_KN_RPTR, key->result_pointer);
65 buf[j++] |= (data << 16);
66 }
67 }
68}
69
70static void xgene_cle_dn_to_hw(const struct xgene_cle_ptree_ewdn *dn,
71 u32 *buf, u32 jb)
72{
73 const struct xgene_cle_ptree_branch *br;
74 u32 i, j = 0;
75 u32 npp;
76
77 buf[j++] = SET_VAL(CLE_DN_TYPE, dn->node_type) |
78 SET_VAL(CLE_DN_LASTN, dn->last_node) |
79 SET_VAL(CLE_DN_HLS, dn->hdr_len_store) |
80 SET_VAL(CLE_DN_EXT, dn->hdr_extn) |
81 SET_VAL(CLE_DN_BSTOR, dn->byte_store) |
82 SET_VAL(CLE_DN_SBSTOR, dn->search_byte_store) |
83 SET_VAL(CLE_DN_RPTR, dn->result_pointer);
84
85 for (i = 0; i < dn->num_branches; i++) {
86 br = &dn->branch[i];
87 npp = br->next_packet_pointer;
88
89 if ((br->jump_rel == JMP_ABS) && (npp < CLE_PKTRAM_SIZE))
90 npp += jb;
91
92 buf[j++] = SET_VAL(CLE_BR_VALID, br->valid) |
93 SET_VAL(CLE_BR_NPPTR, npp) |
94 SET_VAL(CLE_BR_JB, br->jump_bw) |
95 SET_VAL(CLE_BR_JR, br->jump_rel) |
96 SET_VAL(CLE_BR_OP, br->operation) |
97 SET_VAL(CLE_BR_NNODE, br->next_node) |
98 SET_VAL(CLE_BR_NBR, br->next_branch);
99
100 buf[j++] = SET_VAL(CLE_BR_DATA, br->data) |
101 SET_VAL(CLE_BR_MASK, br->mask);
102 }
103}
104
105static int xgene_cle_poll_cmd_done(void __iomem *base,
106 enum xgene_cle_cmd_type cmd)
107{
108 u32 status, loop = 10;
109 int ret = -EBUSY;
110
111 while (loop--) {
112 status = ioread32(base + INDCMD_STATUS);
113 if (status & cmd) {
114 ret = 0;
115 break;
116 }
117 usleep_range(min: 1000, max: 2000);
118 }
119
120 return ret;
121}
122
123static int xgene_cle_dram_wr(struct xgene_enet_cle *cle, u32 *data, u8 nregs,
124 u32 index, enum xgene_cle_dram_type type,
125 enum xgene_cle_cmd_type cmd)
126{
127 enum xgene_cle_parser parser = cle->active_parser;
128 void __iomem *base = cle->base;
129 u32 i, j, ind_addr;
130 u8 port, nparsers;
131 int ret = 0;
132
133 /* PTREE_RAM onwards, DRAM regions are common for all parsers */
134 nparsers = (type >= PTREE_RAM) ? 1 : cle->parsers;
135
136 for (i = 0; i < nparsers; i++) {
137 port = i;
138 if ((type < PTREE_RAM) && (parser != PARSER_ALL))
139 port = parser;
140
141 ind_addr = XGENE_CLE_DRAM(type + (port * 4)) | index;
142 iowrite32(ind_addr, base + INDADDR);
143 for (j = 0; j < nregs; j++)
144 iowrite32(data[j], base + DATA_RAM0 + (j * 4));
145 iowrite32(cmd, base + INDCMD);
146
147 ret = xgene_cle_poll_cmd_done(base, cmd);
148 if (ret)
149 break;
150 }
151
152 return ret;
153}
154
155static void xgene_cle_enable_ptree(struct xgene_enet_pdata *pdata,
156 struct xgene_enet_cle *cle)
157{
158 struct xgene_cle_ptree *ptree = &cle->ptree;
159 void __iomem *addr, *base = cle->base;
160 u32 offset = CLE_PORT_OFFSET;
161 u32 i;
162
163 /* 1G port has to advance 4 bytes and 10G has to advance 8 bytes */
164 ptree->start_pkt += cle->jump_bytes;
165 for (i = 0; i < cle->parsers; i++) {
166 if (cle->active_parser != PARSER_ALL)
167 addr = base + cle->active_parser * offset;
168 else
169 addr = base + (i * offset);
170
171 iowrite32(ptree->start_node & 0x3fff, addr + SNPTR0);
172 iowrite32(ptree->start_pkt & 0x1ff, addr + SPPTR0);
173 }
174}
175
176static int xgene_cle_setup_dbptr(struct xgene_enet_pdata *pdata,
177 struct xgene_enet_cle *cle)
178{
179 struct xgene_cle_ptree *ptree = &cle->ptree;
180 u32 buf[CLE_DRAM_REGS];
181 u32 i;
182 int ret;
183
184 memset(buf, 0, sizeof(buf));
185 for (i = 0; i < ptree->num_dbptr; i++) {
186 xgene_cle_dbptr_to_hw(pdata, dbptr: &ptree->dbptr[i], buf);
187 ret = xgene_cle_dram_wr(cle, data: buf, nregs: 6, index: i + ptree->start_dbptr,
188 type: DB_RAM, cmd: CLE_CMD_WR);
189 if (ret)
190 return ret;
191 }
192
193 return 0;
194}
195
196static const struct xgene_cle_ptree_ewdn xgene_init_ptree_dn[] = {
197 {
198 /* PKT_TYPE_NODE */
199 .node_type = EWDN,
200 .last_node = 0,
201 .hdr_len_store = 1,
202 .hdr_extn = NO_BYTE,
203 .byte_store = NO_BYTE,
204 .search_byte_store = NO_BYTE,
205 .result_pointer = DB_RES_DROP,
206 .num_branches = 2,
207 .branch = {
208 {
209 /* IPV4 */
210 .valid = 1,
211 .next_packet_pointer = 22,
212 .jump_bw = JMP_FW,
213 .jump_rel = JMP_ABS,
214 .operation = EQT,
215 .next_node = PKT_PROT_NODE,
216 .next_branch = 0,
217 .data = 0x8,
218 .mask = 0x0
219 },
220 {
221 .valid = 0,
222 .next_packet_pointer = 262,
223 .jump_bw = JMP_FW,
224 .jump_rel = JMP_ABS,
225 .operation = EQT,
226 .next_node = LAST_NODE,
227 .next_branch = 0,
228 .data = 0x0,
229 .mask = 0xffff
230 }
231 },
232 },
233 {
234 /* PKT_PROT_NODE */
235 .node_type = EWDN,
236 .last_node = 0,
237 .hdr_len_store = 1,
238 .hdr_extn = NO_BYTE,
239 .byte_store = NO_BYTE,
240 .search_byte_store = NO_BYTE,
241 .result_pointer = DB_RES_DROP,
242 .num_branches = 3,
243 .branch = {
244 {
245 /* TCP */
246 .valid = 1,
247 .next_packet_pointer = 26,
248 .jump_bw = JMP_FW,
249 .jump_rel = JMP_ABS,
250 .operation = EQT,
251 .next_node = RSS_IPV4_TCP_NODE,
252 .next_branch = 0,
253 .data = 0x0600,
254 .mask = 0x00ff
255 },
256 {
257 /* UDP */
258 .valid = 1,
259 .next_packet_pointer = 26,
260 .jump_bw = JMP_FW,
261 .jump_rel = JMP_ABS,
262 .operation = EQT,
263 .next_node = RSS_IPV4_UDP_NODE,
264 .next_branch = 0,
265 .data = 0x1100,
266 .mask = 0x00ff
267 },
268 {
269 .valid = 0,
270 .next_packet_pointer = 26,
271 .jump_bw = JMP_FW,
272 .jump_rel = JMP_ABS,
273 .operation = EQT,
274 .next_node = RSS_IPV4_OTHERS_NODE,
275 .next_branch = 0,
276 .data = 0x0,
277 .mask = 0xffff
278 }
279 }
280 },
281 {
282 /* RSS_IPV4_TCP_NODE */
283 .node_type = EWDN,
284 .last_node = 0,
285 .hdr_len_store = 1,
286 .hdr_extn = NO_BYTE,
287 .byte_store = NO_BYTE,
288 .search_byte_store = BOTH_BYTES,
289 .result_pointer = DB_RES_DROP,
290 .num_branches = 6,
291 .branch = {
292 {
293 /* SRC IPV4 B01 */
294 .valid = 0,
295 .next_packet_pointer = 28,
296 .jump_bw = JMP_FW,
297 .jump_rel = JMP_ABS,
298 .operation = EQT,
299 .next_node = RSS_IPV4_TCP_NODE,
300 .next_branch = 1,
301 .data = 0x0,
302 .mask = 0xffff
303 },
304 {
305 /* SRC IPV4 B23 */
306 .valid = 0,
307 .next_packet_pointer = 30,
308 .jump_bw = JMP_FW,
309 .jump_rel = JMP_ABS,
310 .operation = EQT,
311 .next_node = RSS_IPV4_TCP_NODE,
312 .next_branch = 2,
313 .data = 0x0,
314 .mask = 0xffff
315 },
316 {
317 /* DST IPV4 B01 */
318 .valid = 0,
319 .next_packet_pointer = 32,
320 .jump_bw = JMP_FW,
321 .jump_rel = JMP_ABS,
322 .operation = EQT,
323 .next_node = RSS_IPV4_TCP_NODE,
324 .next_branch = 3,
325 .data = 0x0,
326 .mask = 0xffff
327 },
328 {
329 /* DST IPV4 B23 */
330 .valid = 0,
331 .next_packet_pointer = 34,
332 .jump_bw = JMP_FW,
333 .jump_rel = JMP_ABS,
334 .operation = EQT,
335 .next_node = RSS_IPV4_TCP_NODE,
336 .next_branch = 4,
337 .data = 0x0,
338 .mask = 0xffff
339 },
340 {
341 /* TCP SRC Port */
342 .valid = 0,
343 .next_packet_pointer = 36,
344 .jump_bw = JMP_FW,
345 .jump_rel = JMP_ABS,
346 .operation = EQT,
347 .next_node = RSS_IPV4_TCP_NODE,
348 .next_branch = 5,
349 .data = 0x0,
350 .mask = 0xffff
351 },
352 {
353 /* TCP DST Port */
354 .valid = 0,
355 .next_packet_pointer = 256,
356 .jump_bw = JMP_FW,
357 .jump_rel = JMP_ABS,
358 .operation = EQT,
359 .next_node = LAST_NODE,
360 .next_branch = 0,
361 .data = 0x0,
362 .mask = 0xffff
363 }
364 }
365 },
366 {
367 /* RSS_IPV4_UDP_NODE */
368 .node_type = EWDN,
369 .last_node = 0,
370 .hdr_len_store = 1,
371 .hdr_extn = NO_BYTE,
372 .byte_store = NO_BYTE,
373 .search_byte_store = BOTH_BYTES,
374 .result_pointer = DB_RES_DROP,
375 .num_branches = 6,
376 .branch = {
377 {
378 /* SRC IPV4 B01 */
379 .valid = 0,
380 .next_packet_pointer = 28,
381 .jump_bw = JMP_FW,
382 .jump_rel = JMP_ABS,
383 .operation = EQT,
384 .next_node = RSS_IPV4_UDP_NODE,
385 .next_branch = 1,
386 .data = 0x0,
387 .mask = 0xffff
388 },
389 {
390 /* SRC IPV4 B23 */
391 .valid = 0,
392 .next_packet_pointer = 30,
393 .jump_bw = JMP_FW,
394 .jump_rel = JMP_ABS,
395 .operation = EQT,
396 .next_node = RSS_IPV4_UDP_NODE,
397 .next_branch = 2,
398 .data = 0x0,
399 .mask = 0xffff
400 },
401 {
402 /* DST IPV4 B01 */
403 .valid = 0,
404 .next_packet_pointer = 32,
405 .jump_bw = JMP_FW,
406 .jump_rel = JMP_ABS,
407 .operation = EQT,
408 .next_node = RSS_IPV4_UDP_NODE,
409 .next_branch = 3,
410 .data = 0x0,
411 .mask = 0xffff
412 },
413 {
414 /* DST IPV4 B23 */
415 .valid = 0,
416 .next_packet_pointer = 34,
417 .jump_bw = JMP_FW,
418 .jump_rel = JMP_ABS,
419 .operation = EQT,
420 .next_node = RSS_IPV4_UDP_NODE,
421 .next_branch = 4,
422 .data = 0x0,
423 .mask = 0xffff
424 },
425 {
426 /* TCP SRC Port */
427 .valid = 0,
428 .next_packet_pointer = 36,
429 .jump_bw = JMP_FW,
430 .jump_rel = JMP_ABS,
431 .operation = EQT,
432 .next_node = RSS_IPV4_UDP_NODE,
433 .next_branch = 5,
434 .data = 0x0,
435 .mask = 0xffff
436 },
437 {
438 /* TCP DST Port */
439 .valid = 0,
440 .next_packet_pointer = 258,
441 .jump_bw = JMP_FW,
442 .jump_rel = JMP_ABS,
443 .operation = EQT,
444 .next_node = LAST_NODE,
445 .next_branch = 0,
446 .data = 0x0,
447 .mask = 0xffff
448 }
449 }
450 },
451 {
452 /* RSS_IPV4_OTHERS_NODE */
453 .node_type = EWDN,
454 .last_node = 0,
455 .hdr_len_store = 1,
456 .hdr_extn = NO_BYTE,
457 .byte_store = NO_BYTE,
458 .search_byte_store = BOTH_BYTES,
459 .result_pointer = DB_RES_DROP,
460 .num_branches = 6,
461 .branch = {
462 {
463 /* SRC IPV4 B01 */
464 .valid = 0,
465 .next_packet_pointer = 28,
466 .jump_bw = JMP_FW,
467 .jump_rel = JMP_ABS,
468 .operation = EQT,
469 .next_node = RSS_IPV4_OTHERS_NODE,
470 .next_branch = 1,
471 .data = 0x0,
472 .mask = 0xffff
473 },
474 {
475 /* SRC IPV4 B23 */
476 .valid = 0,
477 .next_packet_pointer = 30,
478 .jump_bw = JMP_FW,
479 .jump_rel = JMP_ABS,
480 .operation = EQT,
481 .next_node = RSS_IPV4_OTHERS_NODE,
482 .next_branch = 2,
483 .data = 0x0,
484 .mask = 0xffff
485 },
486 {
487 /* DST IPV4 B01 */
488 .valid = 0,
489 .next_packet_pointer = 32,
490 .jump_bw = JMP_FW,
491 .jump_rel = JMP_ABS,
492 .operation = EQT,
493 .next_node = RSS_IPV4_OTHERS_NODE,
494 .next_branch = 3,
495 .data = 0x0,
496 .mask = 0xffff
497 },
498 {
499 /* DST IPV4 B23 */
500 .valid = 0,
501 .next_packet_pointer = 34,
502 .jump_bw = JMP_FW,
503 .jump_rel = JMP_ABS,
504 .operation = EQT,
505 .next_node = RSS_IPV4_OTHERS_NODE,
506 .next_branch = 4,
507 .data = 0x0,
508 .mask = 0xffff
509 },
510 {
511 /* TCP SRC Port */
512 .valid = 0,
513 .next_packet_pointer = 36,
514 .jump_bw = JMP_FW,
515 .jump_rel = JMP_ABS,
516 .operation = EQT,
517 .next_node = RSS_IPV4_OTHERS_NODE,
518 .next_branch = 5,
519 .data = 0x0,
520 .mask = 0xffff
521 },
522 {
523 /* TCP DST Port */
524 .valid = 0,
525 .next_packet_pointer = 260,
526 .jump_bw = JMP_FW,
527 .jump_rel = JMP_ABS,
528 .operation = EQT,
529 .next_node = LAST_NODE,
530 .next_branch = 0,
531 .data = 0x0,
532 .mask = 0xffff
533 }
534 }
535 },
536
537 {
538 /* LAST NODE */
539 .node_type = EWDN,
540 .last_node = 1,
541 .hdr_len_store = 1,
542 .hdr_extn = NO_BYTE,
543 .byte_store = NO_BYTE,
544 .search_byte_store = NO_BYTE,
545 .result_pointer = DB_RES_DROP,
546 .num_branches = 1,
547 .branch = {
548 {
549 .valid = 0,
550 .next_packet_pointer = 0,
551 .jump_bw = JMP_FW,
552 .jump_rel = JMP_ABS,
553 .operation = EQT,
554 .next_node = MAX_NODES,
555 .next_branch = 0,
556 .data = 0,
557 .mask = 0xffff
558 }
559 }
560 }
561};
562
563static int xgene_cle_setup_node(struct xgene_enet_pdata *pdata,
564 struct xgene_enet_cle *cle)
565{
566 struct xgene_cle_ptree *ptree = &cle->ptree;
567 const struct xgene_cle_ptree_ewdn *dn = xgene_init_ptree_dn;
568 int num_dn = ARRAY_SIZE(xgene_init_ptree_dn);
569 struct xgene_cle_ptree_kn *kn = ptree->kn;
570 u32 buf[CLE_DRAM_REGS];
571 int i, j, ret;
572
573 memset(buf, 0, sizeof(buf));
574 for (i = 0; i < num_dn; i++) {
575 xgene_cle_dn_to_hw(dn: &dn[i], buf, jb: cle->jump_bytes);
576 ret = xgene_cle_dram_wr(cle, data: buf, nregs: 17, index: i + ptree->start_node,
577 type: PTREE_RAM, cmd: CLE_CMD_WR);
578 if (ret)
579 return ret;
580 }
581
582 /* continue node index for key node */
583 memset(buf, 0, sizeof(buf));
584 for (j = i; j < (ptree->num_kn + num_dn); j++) {
585 xgene_cle_kn_to_hw(kn: &kn[j - num_dn], buf);
586 ret = xgene_cle_dram_wr(cle, data: buf, nregs: 17, index: j + ptree->start_node,
587 type: PTREE_RAM, cmd: CLE_CMD_WR);
588 if (ret)
589 return ret;
590 }
591
592 return 0;
593}
594
595static int xgene_cle_setup_ptree(struct xgene_enet_pdata *pdata,
596 struct xgene_enet_cle *cle)
597{
598 int ret;
599
600 ret = xgene_cle_setup_node(pdata, cle);
601 if (ret)
602 return ret;
603
604 ret = xgene_cle_setup_dbptr(pdata, cle);
605 if (ret)
606 return ret;
607
608 xgene_cle_enable_ptree(pdata, cle);
609
610 return 0;
611}
612
613static void xgene_cle_setup_def_dbptr(struct xgene_enet_pdata *pdata,
614 struct xgene_enet_cle *enet_cle,
615 struct xgene_cle_dbptr *dbptr,
616 u32 index, u8 priority)
617{
618 void __iomem *base = enet_cle->base;
619 void __iomem *base_addr;
620 u32 buf[CLE_DRAM_REGS];
621 u32 def_cls, offset;
622 u32 i, j;
623
624 memset(buf, 0, sizeof(buf));
625 xgene_cle_dbptr_to_hw(pdata, dbptr, buf);
626
627 for (i = 0; i < enet_cle->parsers; i++) {
628 if (enet_cle->active_parser != PARSER_ALL) {
629 offset = enet_cle->active_parser *
630 CLE_PORT_OFFSET;
631 } else {
632 offset = i * CLE_PORT_OFFSET;
633 }
634
635 base_addr = base + DFCLSRESDB00 + offset;
636 for (j = 0; j < 6; j++)
637 iowrite32(buf[j], base_addr + (j * 4));
638
639 def_cls = ((priority & 0x7) << 10) | (index & 0x3ff);
640 iowrite32(def_cls, base + DFCLSRESDBPTR0 + offset);
641 }
642}
643
644static int xgene_cle_set_rss_sband(struct xgene_enet_cle *cle)
645{
646 u32 idx = CLE_PKTRAM_SIZE / sizeof(u32);
647 u32 mac_hdr_len = ETH_HLEN;
648 u32 sband, reg = 0;
649 u32 ipv4_ihl = 5;
650 u32 hdr_len;
651 int ret;
652
653 /* Sideband: IPV4/TCP packets */
654 hdr_len = (mac_hdr_len << 5) | ipv4_ihl;
655 xgene_cle_sband_to_hw(frag: 0, ver: XGENE_CLE_IPV4, type: XGENE_CLE_TCP, len: hdr_len, reg: &reg);
656 sband = reg;
657
658 /* Sideband: IPv4/UDP packets */
659 hdr_len = (mac_hdr_len << 5) | ipv4_ihl;
660 xgene_cle_sband_to_hw(frag: 1, ver: XGENE_CLE_IPV4, type: XGENE_CLE_UDP, len: hdr_len, reg: &reg);
661 sband |= (reg << 16);
662
663 ret = xgene_cle_dram_wr(cle, data: &sband, nregs: 1, index: idx, type: PKT_RAM, cmd: CLE_CMD_WR);
664 if (ret)
665 return ret;
666
667 /* Sideband: IPv4/RAW packets */
668 hdr_len = (mac_hdr_len << 5) | ipv4_ihl;
669 xgene_cle_sband_to_hw(frag: 0, ver: XGENE_CLE_IPV4, type: XGENE_CLE_OTHER,
670 len: hdr_len, reg: &reg);
671 sband = reg;
672
673 /* Sideband: Ethernet II/RAW packets */
674 hdr_len = (mac_hdr_len << 5);
675 xgene_cle_sband_to_hw(frag: 0, ver: XGENE_CLE_IPV4, type: XGENE_CLE_OTHER,
676 len: hdr_len, reg: &reg);
677 sband |= (reg << 16);
678
679 ret = xgene_cle_dram_wr(cle, data: &sband, nregs: 1, index: idx + 1, type: PKT_RAM, cmd: CLE_CMD_WR);
680 if (ret)
681 return ret;
682
683 return 0;
684}
685
686static int xgene_cle_set_rss_skeys(struct xgene_enet_cle *cle)
687{
688 u32 secret_key_ipv4[4]; /* 16 Bytes*/
689 int ret = 0;
690
691 get_random_bytes(buf: secret_key_ipv4, len: 16);
692 ret = xgene_cle_dram_wr(cle, data: secret_key_ipv4, nregs: 4, index: 0,
693 type: RSS_IPV4_HASH_SKEY, cmd: CLE_CMD_WR);
694 return ret;
695}
696
697static int xgene_cle_set_rss_idt(struct xgene_enet_pdata *pdata)
698{
699 u32 fpsel, dstqid, nfpsel, idt_reg, idx;
700 int i, ret = 0;
701 u16 pool_id;
702
703 for (i = 0; i < XGENE_CLE_IDT_ENTRIES; i++) {
704 idx = i % pdata->rxq_cnt;
705 pool_id = pdata->rx_ring[idx]->buf_pool->id;
706 fpsel = xgene_enet_get_fpsel(id: pool_id);
707 dstqid = xgene_enet_dst_ring_num(ring: pdata->rx_ring[idx]);
708 nfpsel = 0;
709 if (pdata->rx_ring[idx]->page_pool) {
710 pool_id = pdata->rx_ring[idx]->page_pool->id;
711 nfpsel = xgene_enet_get_fpsel(id: pool_id);
712 }
713
714 idt_reg = 0;
715 xgene_cle_idt_to_hw(pdata, dstqid, fpsel, nfpsel, idt_reg: &idt_reg);
716 ret = xgene_cle_dram_wr(cle: &pdata->cle, data: &idt_reg, nregs: 1, index: i,
717 type: RSS_IDT, cmd: CLE_CMD_WR);
718 if (ret)
719 return ret;
720 }
721
722 ret = xgene_cle_set_rss_skeys(cle: &pdata->cle);
723 if (ret)
724 return ret;
725
726 return 0;
727}
728
729static int xgene_cle_setup_rss(struct xgene_enet_pdata *pdata)
730{
731 struct xgene_enet_cle *cle = &pdata->cle;
732 void __iomem *base = cle->base;
733 u32 offset, val = 0;
734 int i, ret = 0;
735
736 offset = CLE_PORT_OFFSET;
737 for (i = 0; i < cle->parsers; i++) {
738 if (cle->active_parser != PARSER_ALL)
739 offset = cle->active_parser * CLE_PORT_OFFSET;
740 else
741 offset = i * CLE_PORT_OFFSET;
742
743 /* enable RSS */
744 val = (RSS_IPV4_12B << 1) | 0x1;
745 writel(val, addr: base + RSS_CTRL0 + offset);
746 }
747
748 /* setup sideband data */
749 ret = xgene_cle_set_rss_sband(cle);
750 if (ret)
751 return ret;
752
753 /* setup indirection table */
754 ret = xgene_cle_set_rss_idt(pdata);
755 if (ret)
756 return ret;
757
758 return 0;
759}
760
761static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
762{
763 struct xgene_enet_cle *enet_cle = &pdata->cle;
764 u32 def_qid, def_fpsel, def_nxtfpsel, pool_id;
765 struct xgene_cle_dbptr dbptr[DB_MAX_PTRS];
766 struct xgene_cle_ptree *ptree;
767 struct xgene_cle_ptree_kn kn;
768 int ret;
769
770 if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII)
771 return -EINVAL;
772
773 ptree = &enet_cle->ptree;
774 ptree->start_pkt = 12; /* Ethertype */
775
776 ret = xgene_cle_setup_rss(pdata);
777 if (ret) {
778 netdev_err(dev: pdata->ndev, format: "RSS initialization failed\n");
779 return ret;
780 }
781
782 def_qid = xgene_enet_dst_ring_num(ring: pdata->rx_ring[0]);
783 pool_id = pdata->rx_ring[0]->buf_pool->id;
784 def_fpsel = xgene_enet_get_fpsel(id: pool_id);
785 def_nxtfpsel = 0;
786 if (pdata->rx_ring[0]->page_pool) {
787 pool_id = pdata->rx_ring[0]->page_pool->id;
788 def_nxtfpsel = xgene_enet_get_fpsel(id: pool_id);
789 }
790
791 memset(dbptr, 0, sizeof(struct xgene_cle_dbptr) * DB_MAX_PTRS);
792 dbptr[DB_RES_ACCEPT].fpsel = def_fpsel;
793 dbptr[DB_RES_ACCEPT].nxtfpsel = def_nxtfpsel;
794 dbptr[DB_RES_ACCEPT].dstqid = def_qid;
795 dbptr[DB_RES_ACCEPT].cle_priority = 1;
796
797 dbptr[DB_RES_DEF].fpsel = def_fpsel;
798 dbptr[DB_RES_DEF].nxtfpsel = def_nxtfpsel;
799 dbptr[DB_RES_DEF].dstqid = def_qid;
800 dbptr[DB_RES_DEF].cle_priority = 7;
801 xgene_cle_setup_def_dbptr(pdata, enet_cle, dbptr: &dbptr[DB_RES_DEF],
802 index: DB_RES_ACCEPT, priority: 7);
803
804 dbptr[DB_RES_DROP].drop = 1;
805
806 memset(&kn, 0, sizeof(kn));
807 kn.node_type = KN;
808 kn.num_keys = 1;
809 kn.key[0].priority = 0;
810 kn.key[0].result_pointer = DB_RES_ACCEPT;
811
812 ptree->kn = &kn;
813 ptree->dbptr = dbptr;
814 ptree->num_kn = 1;
815 ptree->num_dbptr = DB_MAX_PTRS;
816
817 return xgene_cle_setup_ptree(pdata, cle: enet_cle);
818}
819
820const struct xgene_cle_ops xgene_cle3in_ops = {
821 .cle_init = xgene_enet_cle_init,
822};
823

source code of linux/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c