cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

xgene_enet_cle.c (19064B)


      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};