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(1000, 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, &ptree->dbptr[i], buf);
187		ret = xgene_cle_dram_wr(cle, buf, 6, i + ptree->start_dbptr,
188					DB_RAM,	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[i], buf, cle->jump_bytes);
576		ret = xgene_cle_dram_wr(cle, buf, 17, i + ptree->start_node,
577					PTREE_RAM, 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[j - num_dn], buf);
586		ret = xgene_cle_dram_wr(cle, buf, 17, j + ptree->start_node,
587					PTREE_RAM, 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(0, XGENE_CLE_IPV4, XGENE_CLE_TCP, hdr_len, &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(1, XGENE_CLE_IPV4, XGENE_CLE_UDP, hdr_len, &reg);
661	sband |= (reg << 16);
662
663	ret = xgene_cle_dram_wr(cle, &sband, 1, idx, PKT_RAM, 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(0, XGENE_CLE_IPV4, XGENE_CLE_OTHER,
670			      hdr_len, &reg);
671	sband = reg;
672
673	/* Sideband: Ethernet II/RAW packets */
674	hdr_len = (mac_hdr_len << 5);
675	xgene_cle_sband_to_hw(0, XGENE_CLE_IPV4, XGENE_CLE_OTHER,
676			      hdr_len, &reg);
677	sband |= (reg << 16);
678
679	ret = xgene_cle_dram_wr(cle, &sband, 1, idx + 1, PKT_RAM, 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(secret_key_ipv4, 16);
692	ret = xgene_cle_dram_wr(cle, secret_key_ipv4, 4, 0,
693				RSS_IPV4_HASH_SKEY, 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(pool_id);
707		dstqid = xgene_enet_dst_ring_num(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(pool_id);
712		}
713
714		idt_reg = 0;
715		xgene_cle_idt_to_hw(pdata, dstqid, fpsel, nfpsel, &idt_reg);
716		ret = xgene_cle_dram_wr(&pdata->cle, &idt_reg, 1, i,
717					RSS_IDT, CLE_CMD_WR);
718		if (ret)
719			return ret;
720	}
721
722	ret = xgene_cle_set_rss_skeys(&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, 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(pdata->ndev, "RSS initialization failed\n");
779		return ret;
780	}
781
782	def_qid = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
783	pool_id = pdata->rx_ring[0]->buf_pool->id;
784	def_fpsel = xgene_enet_get_fpsel(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(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[DB_RES_DEF],
802				  DB_RES_ACCEPT, 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, enet_cle);
818}
819
820const struct xgene_cle_ops xgene_cle3in_ops = {
821	.cle_init = xgene_enet_cle_init,
822};
823