mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-15 01:24:33 +00:00
drivers: net: xgene: Add support for Classifier engine
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com> Signed-off-by: Khuong Dinh <kdinh@apm.com> Signed-off-by: Tanmay Inamdar <tinamdar@apm.com> Tested-by: Toan Le <toanle@apm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
e4999f256c
commit
76f94a9c77
@ -3,5 +3,6 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
xgene-enet-objs := xgene_enet_hw.o xgene_enet_sgmac.o xgene_enet_xgmac.o \
|
xgene-enet-objs := xgene_enet_hw.o xgene_enet_sgmac.o xgene_enet_xgmac.o \
|
||||||
xgene_enet_main.o xgene_enet_ring2.o xgene_enet_ethtool.o
|
xgene_enet_main.o xgene_enet_ring2.o xgene_enet_ethtool.o \
|
||||||
|
xgene_enet_cle.o
|
||||||
obj-$(CONFIG_NET_XGENE) += xgene-enet.o
|
obj-$(CONFIG_NET_XGENE) += xgene-enet.o
|
||||||
|
357
drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
Normal file
357
drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
/* Applied Micro X-Gene SoC Ethernet Classifier structures
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016, Applied Micro Circuits Corporation
|
||||||
|
* Authors: Khuong Dinh <kdinh@apm.com>
|
||||||
|
* Tanmay Inamdar <tinamdar@apm.com>
|
||||||
|
* Iyappan Subramanian <isubramanian@apm.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xgene_enet_main.h"
|
||||||
|
|
||||||
|
static void xgene_cle_dbptr_to_hw(struct xgene_enet_pdata *pdata,
|
||||||
|
struct xgene_cle_dbptr *dbptr, u32 *buf)
|
||||||
|
{
|
||||||
|
buf[4] = SET_VAL(CLE_FPSEL, dbptr->fpsel) |
|
||||||
|
SET_VAL(CLE_DSTQIDL, dbptr->dstqid);
|
||||||
|
|
||||||
|
buf[5] = SET_VAL(CLE_DSTQIDH, (u32)dbptr->dstqid >> CLE_DSTQIDL_LEN) |
|
||||||
|
SET_VAL(CLE_PRIORITY, dbptr->cle_priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xgene_cle_kn_to_hw(struct xgene_cle_ptree_kn *kn, u32 *buf)
|
||||||
|
{
|
||||||
|
u32 i, j = 0;
|
||||||
|
u32 data;
|
||||||
|
|
||||||
|
buf[j++] = SET_VAL(CLE_TYPE, kn->node_type);
|
||||||
|
for (i = 0; i < kn->num_keys; i++) {
|
||||||
|
struct xgene_cle_ptree_key *key = &kn->key[i];
|
||||||
|
|
||||||
|
if (!(i % 2)) {
|
||||||
|
buf[j] = SET_VAL(CLE_KN_PRIO, key->priority) |
|
||||||
|
SET_VAL(CLE_KN_RPTR, key->result_pointer);
|
||||||
|
} else {
|
||||||
|
data = SET_VAL(CLE_KN_PRIO, key->priority) |
|
||||||
|
SET_VAL(CLE_KN_RPTR, key->result_pointer);
|
||||||
|
buf[j++] |= (data << 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xgene_cle_dn_to_hw(struct xgene_cle_ptree_ewdn *dn,
|
||||||
|
u32 *buf, u32 jb)
|
||||||
|
{
|
||||||
|
struct xgene_cle_ptree_branch *br;
|
||||||
|
u32 i, j = 0;
|
||||||
|
u32 npp;
|
||||||
|
|
||||||
|
buf[j++] = SET_VAL(CLE_DN_TYPE, dn->node_type) |
|
||||||
|
SET_VAL(CLE_DN_LASTN, dn->last_node) |
|
||||||
|
SET_VAL(CLE_DN_HLS, dn->hdr_len_store) |
|
||||||
|
SET_VAL(CLE_DN_EXT, dn->hdr_extn) |
|
||||||
|
SET_VAL(CLE_DN_BSTOR, dn->byte_store) |
|
||||||
|
SET_VAL(CLE_DN_SBSTOR, dn->search_byte_store) |
|
||||||
|
SET_VAL(CLE_DN_RPTR, dn->result_pointer);
|
||||||
|
|
||||||
|
for (i = 0; i < dn->num_branches; i++) {
|
||||||
|
br = &dn->branch[i];
|
||||||
|
npp = br->next_packet_pointer;
|
||||||
|
|
||||||
|
if ((br->jump_rel == JMP_ABS) && (npp < CLE_PKTRAM_SIZE))
|
||||||
|
npp += jb;
|
||||||
|
|
||||||
|
buf[j++] = SET_VAL(CLE_BR_VALID, br->valid) |
|
||||||
|
SET_VAL(CLE_BR_NPPTR, npp) |
|
||||||
|
SET_VAL(CLE_BR_JB, br->jump_bw) |
|
||||||
|
SET_VAL(CLE_BR_JR, br->jump_rel) |
|
||||||
|
SET_VAL(CLE_BR_OP, br->operation) |
|
||||||
|
SET_VAL(CLE_BR_NNODE, br->next_node) |
|
||||||
|
SET_VAL(CLE_BR_NBR, br->next_branch);
|
||||||
|
|
||||||
|
buf[j++] = SET_VAL(CLE_BR_DATA, br->data) |
|
||||||
|
SET_VAL(CLE_BR_MASK, br->mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xgene_cle_poll_cmd_done(void __iomem *base,
|
||||||
|
enum xgene_cle_cmd_type cmd)
|
||||||
|
{
|
||||||
|
u32 status, loop = 10;
|
||||||
|
int ret = -EBUSY;
|
||||||
|
|
||||||
|
while (loop--) {
|
||||||
|
status = ioread32(base + INDCMD_STATUS);
|
||||||
|
if (status & cmd) {
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
usleep_range(1000, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xgene_cle_dram_wr(struct xgene_enet_cle *cle, u32 *data, u8 nregs,
|
||||||
|
u32 index, enum xgene_cle_dram_type type,
|
||||||
|
enum xgene_cle_cmd_type cmd)
|
||||||
|
{
|
||||||
|
enum xgene_cle_parser parser = cle->active_parser;
|
||||||
|
void __iomem *base = cle->base;
|
||||||
|
u32 i, j, ind_addr;
|
||||||
|
u8 port, nparsers;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
/* PTREE_RAM onwards, DRAM regions are common for all parsers */
|
||||||
|
nparsers = (type >= PTREE_RAM) ? 1 : cle->parsers;
|
||||||
|
|
||||||
|
for (i = 0; i < nparsers; i++) {
|
||||||
|
port = i;
|
||||||
|
if ((type < PTREE_RAM) && (parser != PARSER_ALL))
|
||||||
|
port = parser;
|
||||||
|
|
||||||
|
ind_addr = XGENE_CLE_DRAM(type + (port * 4)) | index;
|
||||||
|
iowrite32(ind_addr, base + INDADDR);
|
||||||
|
for (j = 0; j < nregs; j++)
|
||||||
|
iowrite32(data[j], base + DATA_RAM0 + (j * 4));
|
||||||
|
iowrite32(cmd, base + INDCMD);
|
||||||
|
|
||||||
|
ret = xgene_cle_poll_cmd_done(base, cmd);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xgene_cle_enable_ptree(struct xgene_enet_pdata *pdata,
|
||||||
|
struct xgene_enet_cle *cle)
|
||||||
|
{
|
||||||
|
struct xgene_cle_ptree *ptree = &cle->ptree;
|
||||||
|
void __iomem *addr, *base = cle->base;
|
||||||
|
u32 offset = CLE_PORT_OFFSET;
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
/* 1G port has to advance 4 bytes and 10G has to advance 8 bytes */
|
||||||
|
ptree->start_pkt += cle->jump_bytes;
|
||||||
|
for (i = 0; i < cle->parsers; i++) {
|
||||||
|
if (cle->active_parser != PARSER_ALL)
|
||||||
|
addr = base + cle->active_parser * offset;
|
||||||
|
else
|
||||||
|
addr = base + (i * offset);
|
||||||
|
|
||||||
|
iowrite32(ptree->start_node & 0x3fff, addr + SNPTR0);
|
||||||
|
iowrite32(ptree->start_pkt & 0x1ff, addr + SPPTR0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xgene_cle_setup_dbptr(struct xgene_enet_pdata *pdata,
|
||||||
|
struct xgene_enet_cle *cle)
|
||||||
|
{
|
||||||
|
struct xgene_cle_ptree *ptree = &cle->ptree;
|
||||||
|
u32 buf[CLE_DRAM_REGS];
|
||||||
|
u32 i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
for (i = 0; i < ptree->num_dbptr; i++) {
|
||||||
|
xgene_cle_dbptr_to_hw(pdata, &ptree->dbptr[i], buf);
|
||||||
|
ret = xgene_cle_dram_wr(cle, buf, 6, i + ptree->start_dbptr,
|
||||||
|
DB_RAM, CLE_CMD_WR);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xgene_cle_setup_node(struct xgene_enet_pdata *pdata,
|
||||||
|
struct xgene_enet_cle *cle)
|
||||||
|
{
|
||||||
|
struct xgene_cle_ptree *ptree = &cle->ptree;
|
||||||
|
struct xgene_cle_ptree_ewdn *dn = ptree->dn;
|
||||||
|
struct xgene_cle_ptree_kn *kn = ptree->kn;
|
||||||
|
u32 buf[CLE_DRAM_REGS];
|
||||||
|
int i, j, ret;
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
for (i = 0; i < ptree->num_dn; i++) {
|
||||||
|
xgene_cle_dn_to_hw(&dn[i], buf, cle->jump_bytes);
|
||||||
|
ret = xgene_cle_dram_wr(cle, buf, 17, i + ptree->start_node,
|
||||||
|
PTREE_RAM, CLE_CMD_WR);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* continue node index for key node */
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
for (j = i; j < (ptree->num_kn + ptree->num_dn); j++) {
|
||||||
|
xgene_cle_kn_to_hw(&kn[j - ptree->num_dn], buf);
|
||||||
|
ret = xgene_cle_dram_wr(cle, buf, 17, j + ptree->start_node,
|
||||||
|
PTREE_RAM, CLE_CMD_WR);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xgene_cle_setup_ptree(struct xgene_enet_pdata *pdata,
|
||||||
|
struct xgene_enet_cle *cle)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = xgene_cle_setup_node(pdata, cle);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = xgene_cle_setup_dbptr(pdata, cle);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
xgene_cle_enable_ptree(pdata, cle);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xgene_cle_setup_def_dbptr(struct xgene_enet_pdata *pdata,
|
||||||
|
struct xgene_enet_cle *enet_cle,
|
||||||
|
struct xgene_cle_dbptr *dbptr,
|
||||||
|
u32 index, u8 priority)
|
||||||
|
{
|
||||||
|
void __iomem *base = enet_cle->base;
|
||||||
|
void __iomem *base_addr;
|
||||||
|
u32 buf[CLE_DRAM_REGS];
|
||||||
|
u32 def_cls, offset;
|
||||||
|
u32 i, j;
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
xgene_cle_dbptr_to_hw(pdata, dbptr, buf);
|
||||||
|
|
||||||
|
for (i = 0; i < enet_cle->parsers; i++) {
|
||||||
|
if (enet_cle->active_parser != PARSER_ALL) {
|
||||||
|
offset = enet_cle->active_parser *
|
||||||
|
CLE_PORT_OFFSET;
|
||||||
|
} else {
|
||||||
|
offset = i * CLE_PORT_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
base_addr = base + DFCLSRESDB00 + offset;
|
||||||
|
for (j = 0; j < 6; j++)
|
||||||
|
iowrite32(buf[j], base_addr + (j * 4));
|
||||||
|
|
||||||
|
def_cls = ((priority & 0x7) << 10) | (index & 0x3ff);
|
||||||
|
iowrite32(def_cls, base + DFCLSRESDBPTR0 + offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
|
||||||
|
{
|
||||||
|
struct xgene_enet_cle *enet_cle = &pdata->cle;
|
||||||
|
struct xgene_cle_dbptr dbptr[DB_MAX_PTRS];
|
||||||
|
u32 def_qid, def_fpsel, pool_id;
|
||||||
|
struct xgene_cle_ptree *ptree;
|
||||||
|
struct xgene_cle_ptree_kn kn;
|
||||||
|
struct xgene_cle_ptree_ewdn ptree_dn[] = {
|
||||||
|
{
|
||||||
|
/* PKT_TYPE_NODE */
|
||||||
|
.node_type = EWDN,
|
||||||
|
.last_node = 0,
|
||||||
|
.hdr_len_store = 0,
|
||||||
|
.hdr_extn = NO_BYTE,
|
||||||
|
.byte_store = NO_BYTE,
|
||||||
|
.search_byte_store = NO_BYTE,
|
||||||
|
.result_pointer = DB_RES_DROP,
|
||||||
|
.num_branches = 1,
|
||||||
|
.branch = {
|
||||||
|
{
|
||||||
|
/* Allow all packet type */
|
||||||
|
.valid = 0,
|
||||||
|
.next_packet_pointer = 0,
|
||||||
|
.jump_bw = JMP_FW,
|
||||||
|
.jump_rel = JMP_ABS,
|
||||||
|
.operation = EQT,
|
||||||
|
.next_node = LAST_NODE,
|
||||||
|
.next_branch = 0,
|
||||||
|
.data = 0x0,
|
||||||
|
.mask = 0xffff
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* LAST NODE */
|
||||||
|
.node_type = EWDN,
|
||||||
|
.last_node = 1,
|
||||||
|
.hdr_len_store = 0,
|
||||||
|
.hdr_extn = NO_BYTE,
|
||||||
|
.byte_store = NO_BYTE,
|
||||||
|
.search_byte_store = NO_BYTE,
|
||||||
|
.result_pointer = DB_RES_DROP,
|
||||||
|
.num_branches = 1,
|
||||||
|
.branch = {
|
||||||
|
{
|
||||||
|
.valid = 0,
|
||||||
|
.next_packet_pointer = 0,
|
||||||
|
.jump_bw = JMP_FW,
|
||||||
|
.jump_rel = JMP_ABS,
|
||||||
|
.operation = EQT,
|
||||||
|
.next_node = MAX_NODES,
|
||||||
|
.next_branch = 0,
|
||||||
|
.data = 0,
|
||||||
|
.mask = 0xffff
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ptree = &enet_cle->ptree;
|
||||||
|
ptree->start_pkt = 12; /* Ethertype */
|
||||||
|
|
||||||
|
def_qid = xgene_enet_dst_ring_num(pdata->rx_ring);
|
||||||
|
pool_id = pdata->rx_ring->buf_pool->id;
|
||||||
|
def_fpsel = xgene_enet_ring_bufnum(pool_id) - 0x20;
|
||||||
|
|
||||||
|
memset(dbptr, 0, sizeof(struct xgene_cle_dbptr) * DB_MAX_PTRS);
|
||||||
|
dbptr[DB_RES_ACCEPT].fpsel = def_fpsel;
|
||||||
|
dbptr[DB_RES_ACCEPT].dstqid = def_qid;
|
||||||
|
dbptr[DB_RES_ACCEPT].cle_priority = 1;
|
||||||
|
|
||||||
|
dbptr[DB_RES_DEF].fpsel = def_fpsel;
|
||||||
|
dbptr[DB_RES_DEF].dstqid = def_qid;
|
||||||
|
dbptr[DB_RES_DEF].cle_priority = 7;
|
||||||
|
xgene_cle_setup_def_dbptr(pdata, enet_cle, &dbptr[DB_RES_DEF],
|
||||||
|
DB_RES_ACCEPT, 7);
|
||||||
|
|
||||||
|
dbptr[DB_RES_DROP].drop = 1;
|
||||||
|
|
||||||
|
memset(&kn, 0, sizeof(kn));
|
||||||
|
kn.node_type = KN;
|
||||||
|
kn.num_keys = 1;
|
||||||
|
kn.key[0].priority = 0;
|
||||||
|
kn.key[0].result_pointer = DB_RES_ACCEPT;
|
||||||
|
|
||||||
|
ptree->dn = ptree_dn;
|
||||||
|
ptree->kn = &kn;
|
||||||
|
ptree->dbptr = dbptr;
|
||||||
|
ptree->num_dn = MAX_NODES;
|
||||||
|
ptree->num_kn = 1;
|
||||||
|
ptree->num_dbptr = DB_MAX_PTRS;
|
||||||
|
|
||||||
|
return xgene_cle_setup_ptree(pdata, enet_cle);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct xgene_cle_ops xgene_cle3in_ops = {
|
||||||
|
.cle_init = xgene_enet_cle_init,
|
||||||
|
};
|
254
drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
Normal file
254
drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
/* Applied Micro X-Gene SoC Ethernet Classifier structures
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016, Applied Micro Circuits Corporation
|
||||||
|
* Authors: Khuong Dinh <kdinh@apm.com>
|
||||||
|
* Tanmay Inamdar <tinamdar@apm.com>
|
||||||
|
* Iyappan Subramanian <isubramanian@apm.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XGENE_ENET_CLE_H__
|
||||||
|
#define __XGENE_ENET_CLE_H__
|
||||||
|
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/random.h>
|
||||||
|
|
||||||
|
/* Register offsets */
|
||||||
|
#define INDADDR 0x04
|
||||||
|
#define INDCMD 0x08
|
||||||
|
#define INDCMD_STATUS 0x0c
|
||||||
|
#define DATA_RAM0 0x10
|
||||||
|
#define SNPTR0 0x0100
|
||||||
|
#define SPPTR0 0x0104
|
||||||
|
#define DFCLSRESDBPTR0 0x0108
|
||||||
|
#define DFCLSRESDB00 0x010c
|
||||||
|
|
||||||
|
#define CLE_CMD_TO 10 /* ms */
|
||||||
|
#define CLE_PKTRAM_SIZE 256 /* bytes */
|
||||||
|
#define CLE_PORT_OFFSET 0x200
|
||||||
|
#define CLE_DRAM_REGS 17
|
||||||
|
|
||||||
|
#define CLE_DN_TYPE_LEN 2
|
||||||
|
#define CLE_DN_TYPE_POS 0
|
||||||
|
#define CLE_DN_LASTN_LEN 1
|
||||||
|
#define CLE_DN_LASTN_POS 2
|
||||||
|
#define CLE_DN_HLS_LEN 1
|
||||||
|
#define CLE_DN_HLS_POS 3
|
||||||
|
#define CLE_DN_EXT_LEN 2
|
||||||
|
#define CLE_DN_EXT_POS 4
|
||||||
|
#define CLE_DN_BSTOR_LEN 2
|
||||||
|
#define CLE_DN_BSTOR_POS 6
|
||||||
|
#define CLE_DN_SBSTOR_LEN 2
|
||||||
|
#define CLE_DN_SBSTOR_POS 8
|
||||||
|
#define CLE_DN_RPTR_LEN 12
|
||||||
|
#define CLE_DN_RPTR_POS 12
|
||||||
|
|
||||||
|
#define CLE_BR_VALID_LEN 1
|
||||||
|
#define CLE_BR_VALID_POS 0
|
||||||
|
#define CLE_BR_NPPTR_LEN 9
|
||||||
|
#define CLE_BR_NPPTR_POS 1
|
||||||
|
#define CLE_BR_JB_LEN 1
|
||||||
|
#define CLE_BR_JB_POS 10
|
||||||
|
#define CLE_BR_JR_LEN 1
|
||||||
|
#define CLE_BR_JR_POS 11
|
||||||
|
#define CLE_BR_OP_LEN 3
|
||||||
|
#define CLE_BR_OP_POS 12
|
||||||
|
#define CLE_BR_NNODE_LEN 9
|
||||||
|
#define CLE_BR_NNODE_POS 15
|
||||||
|
#define CLE_BR_NBR_LEN 5
|
||||||
|
#define CLE_BR_NBR_POS 24
|
||||||
|
|
||||||
|
#define CLE_BR_DATA_LEN 16
|
||||||
|
#define CLE_BR_DATA_POS 0
|
||||||
|
#define CLE_BR_MASK_LEN 16
|
||||||
|
#define CLE_BR_MASK_POS 16
|
||||||
|
|
||||||
|
#define CLE_KN_PRIO_POS 0
|
||||||
|
#define CLE_KN_PRIO_LEN 3
|
||||||
|
#define CLE_KN_RPTR_POS 3
|
||||||
|
#define CLE_KN_RPTR_LEN 10
|
||||||
|
#define CLE_TYPE_POS 0
|
||||||
|
#define CLE_TYPE_LEN 2
|
||||||
|
|
||||||
|
#define CLE_DSTQIDL_POS 25
|
||||||
|
#define CLE_DSTQIDL_LEN 7
|
||||||
|
#define CLE_DSTQIDH_POS 0
|
||||||
|
#define CLE_DSTQIDH_LEN 5
|
||||||
|
#define CLE_FPSEL_POS 21
|
||||||
|
#define CLE_FPSEL_LEN 4
|
||||||
|
#define CLE_PRIORITY_POS 5
|
||||||
|
#define CLE_PRIORITY_LEN 3
|
||||||
|
|
||||||
|
#define JMP_ABS 0
|
||||||
|
#define JMP_REL 1
|
||||||
|
#define JMP_FW 0
|
||||||
|
#define JMP_BW 1
|
||||||
|
|
||||||
|
enum xgene_cle_ptree_nodes {
|
||||||
|
PKT_TYPE_NODE,
|
||||||
|
LAST_NODE,
|
||||||
|
MAX_NODES
|
||||||
|
};
|
||||||
|
|
||||||
|
enum xgene_cle_byte_store {
|
||||||
|
NO_BYTE,
|
||||||
|
FIRST_BYTE,
|
||||||
|
SECOND_BYTE,
|
||||||
|
BOTH_BYTES
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Preclassification operation types */
|
||||||
|
enum xgene_cle_node_type {
|
||||||
|
INV,
|
||||||
|
KN,
|
||||||
|
EWDN,
|
||||||
|
RES_NODE
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Preclassification operation types */
|
||||||
|
enum xgene_cle_op_type {
|
||||||
|
EQT,
|
||||||
|
NEQT,
|
||||||
|
LTEQT,
|
||||||
|
GTEQT,
|
||||||
|
AND,
|
||||||
|
NAND
|
||||||
|
};
|
||||||
|
|
||||||
|
enum xgene_cle_parser {
|
||||||
|
PARSER0,
|
||||||
|
PARSER1,
|
||||||
|
PARSER2,
|
||||||
|
PARSER_ALL
|
||||||
|
};
|
||||||
|
|
||||||
|
#define XGENE_CLE_DRAM(type) (((type) & 0xf) << 28)
|
||||||
|
enum xgene_cle_dram_type {
|
||||||
|
PKT_RAM,
|
||||||
|
PTREE_RAM = 0xc,
|
||||||
|
AVL_RAM,
|
||||||
|
DB_RAM
|
||||||
|
};
|
||||||
|
|
||||||
|
enum xgene_cle_cmd_type {
|
||||||
|
CLE_CMD_WR = 1,
|
||||||
|
CLE_CMD_RD = 2,
|
||||||
|
CLE_CMD_AVL_ADD = 8,
|
||||||
|
CLE_CMD_AVL_DEL = 16,
|
||||||
|
CLE_CMD_AVL_SRCH = 32
|
||||||
|
};
|
||||||
|
|
||||||
|
enum xgene_cle_ptree_dbptrs {
|
||||||
|
DB_RES_DROP,
|
||||||
|
DB_RES_DEF,
|
||||||
|
DB_RES_ACCEPT,
|
||||||
|
DB_MAX_PTRS
|
||||||
|
};
|
||||||
|
|
||||||
|
struct xgene_cle_ptree_branch {
|
||||||
|
bool valid;
|
||||||
|
u16 next_packet_pointer;
|
||||||
|
bool jump_bw;
|
||||||
|
bool jump_rel;
|
||||||
|
u8 operation;
|
||||||
|
u16 next_node;
|
||||||
|
u8 next_branch;
|
||||||
|
u16 data;
|
||||||
|
u16 mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct xgene_cle_ptree_ewdn {
|
||||||
|
u8 node_type;
|
||||||
|
bool last_node;
|
||||||
|
bool hdr_len_store;
|
||||||
|
u8 hdr_extn;
|
||||||
|
u8 byte_store;
|
||||||
|
u8 search_byte_store;
|
||||||
|
u16 result_pointer;
|
||||||
|
u8 num_branches;
|
||||||
|
struct xgene_cle_ptree_branch branch[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct xgene_cle_ptree_key {
|
||||||
|
u8 priority;
|
||||||
|
u16 result_pointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct xgene_cle_ptree_kn {
|
||||||
|
u8 node_type;
|
||||||
|
u8 num_keys;
|
||||||
|
struct xgene_cle_ptree_key key[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct xgene_cle_dbptr {
|
||||||
|
u8 split_boundary;
|
||||||
|
u8 mirror_nxtfpsel;
|
||||||
|
u8 mirror_fpsel;
|
||||||
|
u16 mirror_dstqid;
|
||||||
|
u8 drop;
|
||||||
|
u8 mirror;
|
||||||
|
u8 hdr_data_split;
|
||||||
|
u64 hopinfomsbs;
|
||||||
|
u8 DR;
|
||||||
|
u8 HR;
|
||||||
|
u64 hopinfomlsbs;
|
||||||
|
u16 h0enq_num;
|
||||||
|
u8 h0fpsel;
|
||||||
|
u8 nxtfpsel;
|
||||||
|
u8 fpsel;
|
||||||
|
u16 dstqid;
|
||||||
|
u8 cle_priority;
|
||||||
|
u8 cle_flowgroup;
|
||||||
|
u8 cle_perflow;
|
||||||
|
u8 cle_insert_timestamp;
|
||||||
|
u8 stash;
|
||||||
|
u8 in;
|
||||||
|
u8 perprioen;
|
||||||
|
u8 perflowgroupen;
|
||||||
|
u8 perflowen;
|
||||||
|
u8 selhash;
|
||||||
|
u8 selhdrext;
|
||||||
|
u8 mirror_nxtfpsel_msb;
|
||||||
|
u8 mirror_fpsel_msb;
|
||||||
|
u8 hfpsel_msb;
|
||||||
|
u8 nxtfpsel_msb;
|
||||||
|
u8 fpsel_msb;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct xgene_cle_ptree {
|
||||||
|
struct xgene_cle_ptree_ewdn *dn;
|
||||||
|
struct xgene_cle_ptree_kn *kn;
|
||||||
|
struct xgene_cle_dbptr *dbptr;
|
||||||
|
u32 num_dn;
|
||||||
|
u32 num_kn;
|
||||||
|
u32 num_dbptr;
|
||||||
|
u32 start_node;
|
||||||
|
u32 start_pkt;
|
||||||
|
u32 start_dbptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct xgene_enet_cle {
|
||||||
|
void __iomem *base;
|
||||||
|
struct xgene_cle_ptree ptree;
|
||||||
|
enum xgene_cle_parser active_parser;
|
||||||
|
u32 parsers;
|
||||||
|
u32 max_nodes;
|
||||||
|
u32 max_dbptrs;
|
||||||
|
u32 jump_bytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct xgene_cle_ops xgene_cle3in_ops;
|
||||||
|
|
||||||
|
#endif /* __XGENE_ENET_CLE_H__ */
|
@ -101,6 +101,7 @@ enum xgene_enet_rm {
|
|||||||
#define MAC_OFFSET 0x30
|
#define MAC_OFFSET 0x30
|
||||||
|
|
||||||
#define BLOCK_ETH_CSR_OFFSET 0x2000
|
#define BLOCK_ETH_CSR_OFFSET 0x2000
|
||||||
|
#define BLOCK_ETH_CLE_CSR_OFFSET 0x6000
|
||||||
#define BLOCK_ETH_RING_IF_OFFSET 0x9000
|
#define BLOCK_ETH_RING_IF_OFFSET 0x9000
|
||||||
#define BLOCK_ETH_CLKRST_CSR_OFFSET 0xc000
|
#define BLOCK_ETH_CLKRST_CSR_OFFSET 0xc000
|
||||||
#define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000
|
#define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000
|
||||||
|
@ -93,13 +93,6 @@ static int xgene_enet_refill_bufpool(struct xgene_enet_desc_ring *buf_pool,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16 xgene_enet_dst_ring_num(struct xgene_enet_desc_ring *ring)
|
|
||||||
{
|
|
||||||
struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
|
|
||||||
|
|
||||||
return ((u16)pdata->rm << 10) | ring->num;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u8 xgene_enet_hdr_len(const void *data)
|
static u8 xgene_enet_hdr_len(const void *data)
|
||||||
{
|
{
|
||||||
const struct ethhdr *eth = data;
|
const struct ethhdr *eth = data;
|
||||||
@ -1278,6 +1271,7 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
|
|||||||
else
|
else
|
||||||
base_addr = pdata->base_addr;
|
base_addr = pdata->base_addr;
|
||||||
pdata->eth_csr_addr = base_addr + BLOCK_ETH_CSR_OFFSET;
|
pdata->eth_csr_addr = base_addr + BLOCK_ETH_CSR_OFFSET;
|
||||||
|
pdata->cle.base = base_addr + BLOCK_ETH_CLE_CSR_OFFSET;
|
||||||
pdata->eth_ring_if_addr = base_addr + BLOCK_ETH_RING_IF_OFFSET;
|
pdata->eth_ring_if_addr = base_addr + BLOCK_ETH_RING_IF_OFFSET;
|
||||||
pdata->eth_diag_csr_addr = base_addr + BLOCK_ETH_DIAG_CSR_OFFSET;
|
pdata->eth_diag_csr_addr = base_addr + BLOCK_ETH_DIAG_CSR_OFFSET;
|
||||||
if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII ||
|
if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII ||
|
||||||
@ -1298,6 +1292,7 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
|
|||||||
|
|
||||||
static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
|
static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
|
||||||
{
|
{
|
||||||
|
struct xgene_enet_cle *enet_cle = &pdata->cle;
|
||||||
struct net_device *ndev = pdata->ndev;
|
struct net_device *ndev = pdata->ndev;
|
||||||
struct xgene_enet_desc_ring *buf_pool;
|
struct xgene_enet_desc_ring *buf_pool;
|
||||||
u16 dst_ring_num;
|
u16 dst_ring_num;
|
||||||
@ -1323,7 +1318,24 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring);
|
dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring);
|
||||||
pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id);
|
if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
|
||||||
|
/* Initialize and Enable PreClassifier Tree */
|
||||||
|
enet_cle->max_nodes = 512;
|
||||||
|
enet_cle->max_dbptrs = 1024;
|
||||||
|
enet_cle->parsers = 3;
|
||||||
|
enet_cle->active_parser = PARSER_ALL;
|
||||||
|
enet_cle->ptree.start_node = 0;
|
||||||
|
enet_cle->ptree.start_dbptr = 0;
|
||||||
|
enet_cle->jump_bytes = 8;
|
||||||
|
ret = pdata->cle_ops->cle_init(pdata);
|
||||||
|
if (ret) {
|
||||||
|
netdev_err(ndev, "Preclass Tree init error\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id);
|
||||||
|
}
|
||||||
|
|
||||||
pdata->mac_ops->init(pdata);
|
pdata->mac_ops->init(pdata);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -1345,6 +1357,7 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
|
|||||||
default:
|
default:
|
||||||
pdata->mac_ops = &xgene_xgmac_ops;
|
pdata->mac_ops = &xgene_xgmac_ops;
|
||||||
pdata->port_ops = &xgene_xgport_ops;
|
pdata->port_ops = &xgene_xgport_ops;
|
||||||
|
pdata->cle_ops = &xgene_cle3in_ops;
|
||||||
pdata->rm = RM0;
|
pdata->rm = RM0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include <linux/if_vlan.h>
|
#include <linux/if_vlan.h>
|
||||||
#include <linux/phy.h>
|
#include <linux/phy.h>
|
||||||
#include "xgene_enet_hw.h"
|
#include "xgene_enet_hw.h"
|
||||||
|
#include "xgene_enet_cle.h"
|
||||||
#include "xgene_enet_ring2.h"
|
#include "xgene_enet_ring2.h"
|
||||||
|
|
||||||
#define XGENE_DRV_VERSION "v1.0"
|
#define XGENE_DRV_VERSION "v1.0"
|
||||||
@ -145,6 +146,10 @@ struct xgene_ring_ops {
|
|||||||
u32 (*len)(struct xgene_enet_desc_ring *);
|
u32 (*len)(struct xgene_enet_desc_ring *);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct xgene_cle_ops {
|
||||||
|
int (*cle_init)(struct xgene_enet_pdata *pdata);
|
||||||
|
};
|
||||||
|
|
||||||
/* ethernet private data */
|
/* ethernet private data */
|
||||||
struct xgene_enet_pdata {
|
struct xgene_enet_pdata {
|
||||||
struct net_device *ndev;
|
struct net_device *ndev;
|
||||||
@ -174,10 +179,12 @@ struct xgene_enet_pdata {
|
|||||||
void __iomem *ring_cmd_addr;
|
void __iomem *ring_cmd_addr;
|
||||||
int phy_mode;
|
int phy_mode;
|
||||||
enum xgene_enet_rm rm;
|
enum xgene_enet_rm rm;
|
||||||
|
struct xgene_enet_cle cle;
|
||||||
struct rtnl_link_stats64 stats;
|
struct rtnl_link_stats64 stats;
|
||||||
const struct xgene_mac_ops *mac_ops;
|
const struct xgene_mac_ops *mac_ops;
|
||||||
const struct xgene_port_ops *port_ops;
|
const struct xgene_port_ops *port_ops;
|
||||||
struct xgene_ring_ops *ring_ops;
|
struct xgene_ring_ops *ring_ops;
|
||||||
|
struct xgene_cle_ops *cle_ops;
|
||||||
struct delayed_work link_work;
|
struct delayed_work link_work;
|
||||||
u32 port_id;
|
u32 port_id;
|
||||||
u8 cpu_bufnum;
|
u8 cpu_bufnum;
|
||||||
@ -229,6 +236,13 @@ static inline struct device *ndev_to_dev(struct net_device *ndev)
|
|||||||
return ndev->dev.parent;
|
return ndev->dev.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline u16 xgene_enet_dst_ring_num(struct xgene_enet_desc_ring *ring)
|
||||||
|
{
|
||||||
|
struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
|
||||||
|
|
||||||
|
return ((u16)pdata->rm << 10) | ring->num;
|
||||||
|
}
|
||||||
|
|
||||||
void xgene_enet_set_ethtool_ops(struct net_device *netdev);
|
void xgene_enet_set_ethtool_ops(struct net_device *netdev);
|
||||||
|
|
||||||
#endif /* __XGENE_ENET_MAIN_H__ */
|
#endif /* __XGENE_ENET_MAIN_H__ */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user