// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Broadcom Starfighter 2 DSA switch CFP support
*
* Copyright (C) 2016, Broadcom
*/
#include <linux/list.h>
#include <linux/ethtool.h>
#include <linux/if_ether.h>
#include <linux/in.h>
#include <linux/netdevice.h>
#include <net/dsa.h>
#include <linux/bitmap.h>
#include <net/flow_offload.h>
#include <net/switchdev.h>
#include <uapi/linux/if_bridge.h>
#include "bcm_sf2.h"
#include "bcm_sf2_regs.h"
struct cfp_rule {
int port;
struct ethtool_rx_flow_spec fs;
struct list_head next;
};
struct cfp_udf_slice_layout {
u8 slices[UDFS_PER_SLICE];
u32 mask_value;
u32 base_offset;
};
struct cfp_udf_layout {
struct cfp_udf_slice_layout udfs[UDF_NUM_SLICES];
};
static const u8 zero_slice[UDFS_PER_SLICE] = { };
/* UDF slices layout for a TCPv4/UDPv4 specification */
static const struct cfp_udf_layout udf_tcpip4_layout = {
.udfs = {
[1] = {
.slices = {
/* End of L2, byte offset 12, src IP[0:15] */
CFG_UDF_EOL2 | 6,
/* End of L2, byte offset 14, src IP[16:31] */
CFG_UDF_EOL2 | 7,
/* End of L2, byte offset 16, dst IP[0:15] */
CFG_UDF_EOL2 | 8,
/* End of L2, byte offset 18, dst IP[16:31] */
CFG_UDF_EOL2 | 9,
/* End of L3, byte offset 0, src port */
CFG_UDF_EOL3 | 0,
/* End of L3, byte offset 2, dst port */
CFG_UDF_EOL3 | 1,
0, 0, 0
},
.mask_value = L3_FRAMING_MASK | IPPROTO_MASK | IP_FRAG,
.base_offset = CORE_UDF_0_A_0_8_PORT_0 + UDF_SLICE_OFFSET,
},
},
};
/* UDF slices layout for a TCPv6/UDPv6 specification */
static const struct cfp_udf_layout udf_tcpip6_layout = {
.udfs = {
[0] = {
.slices = {
/* End of L2, byte offset 8, src IP[0:15] */
CFG_UDF_EOL2 | 4,
/* End of L2, byte offset 10, src IP[16:31] */
CFG_UDF_EOL2 | 5,
/* End of L2, byte offset 12, src IP[32:47] */
CFG_UDF_EOL2 | 6,
/* End of L2, byte offset 14, src IP[48:63] */
CFG_UDF_EOL2 | 7,
/* End of L2, byte offset 16, src IP[64:79] */
CFG_UDF_EOL2 | 8,
/* End of L2, byte offset 18, src IP[80:95] */
CFG_UDF_EOL2 | 9,
/* End of L2, byte offset 20, src IP[96:111] */
CFG_UDF_EOL2 | 10,
/* End of L2, byte offset 22, src IP[112:127] */
CFG_UDF_EOL2 | 11,
/* End of L3, byte offset 0, src port */
CFG_UDF_EOL3 | 0,
},
.mask_value = L3_FRAMING_MASK | IPPROTO_MASK | IP_FRAG,
.base_offset = CORE_UDF_0_B_0_8_PORT_0,
},
[3] = {
.slices = {
/* End of L2, byte offset 24, dst IP[0:15] */
CFG_UDF_EOL2 | 12,
/* End of L2, byte offset 26, dst IP[16:31] */
CFG_UDF_EOL2 | 13,
/* End of L2, byte offset 28, dst IP[32:47] */
CFG_UDF_EOL2 | 14,
/* End of L2, byte offset 30, dst IP[48:63] */
CFG_UDF_EOL2 | 15,
/* End of L2, byte offset 32, dst IP[64:79] */
CFG_UDF_EOL2 | 16,
/* End of L2, byte offset 34, dst IP[80:95] */
CFG_UDF_EOL2 | 17,
/* End of L2, byte offset 36, dst IP[96:111] */
CFG_UDF_EOL2 | 18