/*
 * Broadcom Starfighter 2 DSA switch CFP support
 *
 * Copyright (C) 2016, Broadcom
 *
 * 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.
 */

#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 "bcm_sf2.h"
#include "bcm_sf2_regs.h"

struct cfp_udf_layout {
	u8 slices[UDF_NUM_SLICES];
	u32 mask_value;

};

/* UDF slices layout for a TCPv4/UDPv4 specification */
static const struct cfp_udf_layout udf_tcpip4_layout = {
	.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,
};

static inline unsigned int bcm_sf2_get_num_udf_slices(const u8 *layout)
{
	unsigned int i, count = 0;

	for (i = 0; i < UDF_NUM_SLICES; i++) {
		if (layout[i] != 0)
			count++;
	}

	return count;
}

static void bcm_sf2_cfp_udf_set(struct bcm_sf2_priv *priv,
				unsigned int slice_num,
				const u8 *layout)
{
	u32 offset = CORE_UDF_0_A_0_8_PORT_0 + slice_num * UDF_SLICE_OFFSET;
	unsigned int i;

	for (i = 0; i < UDF_NUM_SLICES; i++)
		core_writel(priv, layout[i], offset + i * 4);
}

static int bcm_sf2_cfp_op(struct bcm_sf2_priv *priv, unsigned int op)
{
	unsigned int timeout = 1000;
	u32 reg;

	reg = core_readl(priv, CORE_CFP_ACC);
	reg &= ~(OP_SEL_MASK | RAM_SEL_MASK);
	reg |= OP_STR_DONE | op;
	core_writel(priv, reg, CORE_CFP_ACC);

	do {
		reg = core_readl(priv, CORE_CFP_ACC);
		if (!(reg & OP_STR_DONE))
			break;

		cpu_relax();
	} while (timeout--);

	if (!timeout)
		return -ETIMEDOUT;

	return 0;
}

static inline void bcm_sf2_cfp_rule_addr_set(struct bcm_sf2_priv *priv,
					     unsigned int addr)
{
	u32 reg;

	WARN_ON(addr >= priv->num_cfp_rules);

	reg = core_readl(priv, CORE_CFP_ACC);
	reg &= ~(XCESS_ADDR_MASK << XCESS_ADDR_SHIFT);
	reg |= addr << XCESS_ADDR_SHIFT;
	core_writel(priv, reg, CORE_CFP_ACC);
}

static inline unsigned int bcm_sf2_cfp_rule_size(struct bcm_sf2_priv *priv)
{
	/* Entry #0 is reserved */
	return priv->num_cfp_rules - 1;
}

static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port,
				struct ethtool_rx_flow_spec *fs)
{
	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
	struct ethtool_tcpip4_spec *v4_spec;
	const struct cfp_udf_layout *layout;
	unsigned int slice_num, rule_index;
	unsigned int queue_num, port_num;
	u8 ip_proto, ip_frag;
	u8 num_udf;
	u32 reg;
	int ret;

	/* Check for unsupported extensions */
	if ((fs->flow_type & FLOW_EXT) &&
	    (fs->m_ext.vlan_etype || fs->m_ext.data[1]))
		return -EINVAL;

	if (fs->location != RX_CLS_LOC_ANY && fs->location >= CFP_NUM_RULES)
		return -EINVAL;

	if (fs->location != RX_CLS_LOC_ANY &&
	    test_bit(fs->location, priv->cfp.used))
		return -EBUSY;

	if (fs->location != RX_CLS_LOC_ANY &&
	    fs->location > bcm_sf2_cfp_rule_size(priv))
		return -EINVAL;

	ip_frag = be32_to_cpu(fs->m_ext.data[0]);

	/* We do not support discarding packets, check that the
	 * destination port is enabled and that we are within the
	 * number of ports supported by the switch
	 */
	port_num = fs->ring_cookie / 8;

	if (fs->ring_cookie == RX_CLS_FLOW_DISC ||
	    !(BIT(port_num) & ds->enabled_port_mask) ||
	    port_num >= priv->hw_params.num_ports)
		return -EINVAL;

	switch (fs->flow_type & ~FLOW_EXT) {
	case TCP_V4_FLOW:
		ip_proto = IPPROTO_TCP;
		v4_spec = &fs->h_u.tcp_ip4_spec;
		break;
	case UDP_V4_FLOW:
		ip_proto = IPPROTO_UDP;
		v4_spec = &fs->h_u.udp_ip4_spec;
		break;
	default:
		return -EINVAL;
	}

	/* We only use one UDF slice for now */
	slice_num = 1;
	layout = &udf_tcpip4_layout;
	num_udf = bcm_sf2_get_num_udf_slices(layout->slices);

	/* Apply the UDF layout for this filter */
	bcm_sf2_cfp_udf_set(priv, slice_num, layout->slices);

	/* Apply to all packets received through this port */
	core_writel(priv, BIT(port), CORE_CFP_DATA_PORT(7));

	/* S-Tag status		[31:30]
	 * C-Tag status		[29:28]
	 * L2 framing		[27:26]
	 * L3 framing		[25:24]
	 * IP ToS		[23:16]
	 * IP proto		[15:08]
	 * IP Fragm		[7]
	 * Non 1st frag		[6]
	 * IP Authen		[5]
	 * TTL range		[4:3]
	 * PPPoE session	[2]
	 * Reserved		[1]
	 * UDF_Valid[8]		[0]
	 */
	core_writel(priv, v4_spec->tos << 16 | ip_proto << 8 | ip_frag << 7,
		    CORE_CFP_DATA_PORT(6));

	/* UDF_Valid[7:0]	[31:24]
	 * S-Tag		[23:8]
	 * C-Tag		[7:0]
	 */
	core_writel(priv, GENMASK(num_udf - 1, 0) << 24, CORE_CFP_DATA_PORT(5));

	/* C-Tag		[31:24]
	 * UDF_n_A8		[23:8]
	 * UDF_n_A7		[7:0]
	 */
	core_writel(priv, 0, CORE_CFP_DATA_PORT(4));

	/* UDF_n_A7		[31:24]
	 * UDF_n_A6		[23:8]
	 * UDF_n_A5		[7:0]
	 */
	core_writel(priv, be16_to_cpu(v4_spec->pdst) >> 8,
		    CORE_CFP_DATA_PORT(3));

	/* UDF_n_A5		[31:24]
	 * UDF_n_A4		[23:8]
	 * UDF_n_A3		[7:0]
	 */
	reg = (be16_to_cpu(v4_spec->pdst) & 0xff) << 24 |
	      (u32)be16_to_cpu(v4_spec->psrc) << 8 |
	      (be32_to_cpu(v4_spec->ip4dst) & 0x0000ff00) >> 8;
	core_writel(priv, reg, CORE_CFP_DATA_PORT(2));

	/* UDF_n_A3		[31:24]
	 * UDF_n_A2		[23:8]
	 * UDF_n_A1		[7:0]
	 */
	reg = (u32)(be32_to_cpu(v4_spec->ip4dst) & 0xff) << 24 |
	      (u32)(be32_to_cpu(v4_spec->ip4dst) >> 16) << 8 |
	      (be32_to_cpu(v4_spec->ip4src) & 0x0000ff00) >> 8;
	core_writel(priv, reg, CORE_CFP_DATA_PORT(1));

	/* UDF_n_A1		[31:24]
	 * UDF_n_A0		[23:8]
	 * Reserved		[7:4]
	 * Slice ID		[3:2]
	 * Slice valid		[1:0]
	 */
	reg = (u32)(be32_to_cpu(v4_spec->ip4src) & 0xff) << 24 |
	      (u32)(be32_to_cpu(v4_spec->ip4src) >> 16) << 8 |
	      SLICE_NUM(slice_num) | SLICE_VALID;
	core_writel(priv, reg, CORE_CFP_DATA_PORT(0));

	/* Source port map match */
	core_writel(priv, 0xff, CORE_CFP_MASK_PORT(7));

	/* Mask with the specific layout for IPv4 packets */
	core_writel(priv, layout->mask_value, CORE_CFP_MASK_PORT(6));

	/* Mask all but valid UDFs */
	core_writel(priv, GENMASK(num_udf - 1, 0) << 24, CORE_CFP_MASK_PORT(5));

	/* Mask all */
	core_writel(priv, 0, CORE_CFP_MASK_PORT(4));

	/* All other UDFs should be matched with the filter */
	core_writel(priv, 0xff, CORE_CFP_MASK_PORT(3));
	core_writel(priv, 0xffffffff, CORE_CFP_MASK_PORT(2));
	core_writel(priv, 0xffffffff, CORE_CFP_MASK_PORT(1));
	core_writel(priv, 0xffffff0f, CORE_CFP_MASK_PORT(0));

	/* Locate the first rule available */
	if (fs->location == RX_CLS_LOC_ANY)
		rule_index = find_first_zero_bit(priv->cfp.used,
						 bcm_sf2_cfp_rule_size(priv));
	else
		rule_index = fs->location;

	/* Insert into TCAM now */
	bcm_sf2_cfp_rule_addr_set(priv, rule_index);

	ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL);
	if (ret) {
		pr_err("TCAM entry at addr %d failed\n", rule_index);
		return ret;
	}

	/* Replace ARL derived destination with DST_MAP derived, define
	 * which port and queue this should be forwarded to.
	 *
	 * We have a small oddity where Port 6 just does not have a
	 * valid bit here (so we subtract by one).
	 */
	queue_num = fs->ring_cookie % 8;
	if (port_num >= 7)
		port_num -= 1;

	reg = CHANGE_FWRD_MAP_IB_REP_ARL | BIT(port_num + DST_MAP_IB_SHIFT) |
		CHANGE_TC | queue_num << NEW_TC_SHIFT;

	core_writel(priv, reg, CORE_ACT_POL_DATA0);

	/* Set classification ID that needs to be put in Broadcom tag */
	core_writel(priv, rule_index << CHAIN_ID_SHIFT,
		    CORE_ACT_POL_DATA1);

	core_writel(priv, 0, CORE_ACT_POL_DATA2);

	/* Configure policer RAM now */
	ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | ACT_POL_RAM);
	if (ret) {
		pr_err("Policer entry at %d failed\n", rule_index);
		return ret;
	}

	/* Disable the policer */
	core_writel(priv, POLICER_MODE_DISABLE, CORE_RATE_METER0);

	/* Now the rate meter */
	ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | RATE_METER_RAM);
	if (ret) {
		pr_err("Meter entry at %d failed\n", rule_index);
		return ret;
	}

	/* Turn on CFP for this rule now */
	reg = core_readl(priv, CORE_CFP_CTL_REG);
	reg |= BIT(port);
	core_writel(priv, reg, CORE_CFP_CTL_REG);

	/* Flag the rule as being used and return it */
	set_bit(rule_index, priv->cfp.used);
	fs->location = rule_index;

	return 0;
}

static int bcm_sf2_cfp_rule_del(struct bcm_sf2_priv *priv, int port,
				u32 loc)
{
	int ret;
	u32 reg;

	if (loc >= CFP_NUM_RULES)
		return -EINVAL;

	/* Refuse deletion of unused rules, and the default reserved rule */
	if (!test_bit(loc, priv->cfp.used) || loc == 0)
		return -EINVAL;

	/* Indicate which rule we want to read */
	bcm_sf2_cfp_rule_addr_set(priv, loc);

	ret =  bcm_sf2_cfp_op(priv, OP_SEL_READ | TCAM_SEL);
	if (ret)
		return ret;

	/* Clear its valid bits */
	reg = core_readl(priv, CORE_CFP_DATA_PORT(0));
	reg &= ~SLICE_VALID;
	core_writel(priv, reg, CORE_CFP_DATA_PORT(0));

	/* Write back this entry into the TCAM now */
	ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL);
	if (ret)
		return ret;

	clear_bit(loc, priv->cfp.used);

	return 0;
}

static void bcm_sf2_invert_masks(struct ethtool_rx_flow_spec *flow)
{
	unsigned int i;

	for (i = 0; i < sizeof(flow->m_u); i++)
		flow->m_u.hdata[i] ^= 0xff;

	flow->m_ext.vlan_etype ^= cpu_to_be16(~0);
	flow->m_ext.vlan_tci ^= cpu_to_be16(~0);
	flow->m_ext.data[0] ^= cpu_to_be32(~0);
	flow->m_ext.data[1] ^= cpu_to_be32(~0);
}

static int bcm_sf2_cfp_rule_get(struct bcm_sf2_priv *priv, int port,
				struct ethtool_rxnfc *nfc, bool search)
{
	struct ethtool_tcpip4_spec *v4_spec;
	unsigned int queue_num;
	u16 src_dst_port;
	u32 reg, ipv4;
	int ret;

	if (!search) {
		bcm_sf2_cfp_rule_addr_set(priv, nfc->fs.location);

		ret = bcm_sf2_cfp_op(priv, OP_SEL_READ | ACT_POL_RAM);
		if (ret)
			return ret;

		reg = core_readl(priv, CORE_ACT_POL_DATA0);

		ret = bcm_sf2_cfp_op(priv, OP_SEL_READ | TCAM_SEL);
		if (ret)
			return ret;
	} else {
		reg = core_readl(priv, CORE_ACT_POL_DATA0);
	}

	/* Extract the destination port */
	nfc->fs.ring_cookie = fls((reg >> DST_MAP_IB_SHIFT) &
				  DST_MAP_IB_MASK) - 1;

	/* There is no Port 6, so we compensate for that here */
	if (nfc->fs.ring_cookie >= 6)
		nfc->fs.ring_cookie++;
	nfc->fs.ring_cookie *= 8;

	/* Extract the destination queue */
	queue_num = (reg >> NEW_TC_SHIFT) & NEW_TC_MASK;
	nfc->fs.ring_cookie += queue_num;

	/* Extract the IP protocol */
	reg = core_readl(priv, CORE_CFP_DATA_PORT(6));
	switch ((reg & IPPROTO_MASK) >> IPPROTO_SHIFT) {
	case IPPROTO_TCP:
		nfc->fs.flow_type = TCP_V4_FLOW;
		v4_spec = &nfc->fs.h_u.tcp_ip4_spec;
		break;
	case IPPROTO_UDP:
		nfc->fs.flow_type = UDP_V4_FLOW;
		v4_spec = &nfc->fs.h_u.udp_ip4_spec;
		break;
	default:
		/* Clear to exit the search process */
		if (search)
			core_readl(priv, CORE_CFP_DATA_PORT(7));
		return -EINVAL;
	}

	v4_spec->tos = (reg >> 16) & IPPROTO_MASK;
	nfc->fs.m_ext.data[0] = cpu_to_be32((reg >> 7) & 1);

	reg = core_readl(priv, CORE_CFP_DATA_PORT(3));
	/* src port [15:8] */
	src_dst_port = reg << 8;

	reg = core_readl(priv, CORE_CFP_DATA_PORT(2));
	/* src port [7:0] */
	src_dst_port |= (reg >> 24);

	v4_spec->pdst = cpu_to_be16(src_dst_port);
	nfc->fs.m_u.tcp_ip4_spec.pdst = cpu_to_be16(~0);
	v4_spec->psrc = cpu_to_be16((u16)(reg >> 8));
	nfc->fs.m_u.tcp_ip4_spec.psrc = cpu_to_be16(~0);

	/* IPv4 dst [15:8] */
	ipv4 = (reg & 0xff) << 8;
	reg = core_readl(priv, CORE_CFP_DATA_PORT(1));
	/* IPv4 dst [31:16] */
	ipv4 |= ((reg >> 8) & 0xffff) << 16;
	/* IPv4 dst [7:0] */
	ipv4 |= (reg >> 24) & 0xff;
	v4_spec->ip4dst = cpu_to_be32(ipv4);
	nfc->fs.m_u.tcp_ip4_spec.ip4dst = cpu_to_be32(~0);

	/* IPv4 src [15:8] */
	ipv4 = (reg & 0xff) << 8;
	reg = core_readl(priv, CORE_CFP_DATA_PORT(0));

	if (!(reg & SLICE_VALID))
		return -EINVAL;

	/* IPv4 src [7:0] */
	ipv4 |= (reg >> 24) & 0xff;
	/* IPv4 src [31:16] */
	ipv4 |= ((reg >> 8) & 0xffff) << 16;
	v4_spec->ip4src = cpu_to_be32(ipv4);
	nfc->fs.m_u.tcp_ip4_spec.ip4src = cpu_to_be32(~0);

	/* Read last to avoid next entry clobbering the results during search
	 * operations
	 */
	reg = core_readl(priv, CORE_CFP_DATA_PORT(7));
	if (!(reg & 1 << port))
		return -EINVAL;

	bcm_sf2_invert_masks(&nfc->fs);

	/* Put the TCAM size here */
	nfc->data = bcm_sf2_cfp_rule_size(priv);

	return 0;
}

/* We implement the search doing a TCAM search operation */
static int bcm_sf2_cfp_rule_get_all(struct bcm_sf2_priv *priv,
				    int port, struct ethtool_rxnfc *nfc,
				    u32 *rule_locs)
{
	unsigned int index = 1, rules_cnt = 0;
	int ret;
	u32 reg;

	/* Do not poll on OP_STR_DONE to be self-clearing for search
	 * operations, we cannot use bcm_sf2_cfp_op here because it completes
	 * on clearing OP_STR_DONE which won't clear until the entire search
	 * operation is over.
	 */
	reg = core_readl(priv, CORE_CFP_ACC);
	reg &= ~(XCESS_ADDR_MASK << XCESS_ADDR_SHIFT);
	reg |= index << XCESS_ADDR_SHIFT;
	reg &= ~(OP_SEL_MASK | RAM_SEL_MASK);
	reg |= OP_SEL_SEARCH | TCAM_SEL | OP_STR_DONE;
	core_writel(priv, reg, CORE_CFP_ACC);

	do {
		/* Wait for results to be ready */
		reg = core_readl(priv, CORE_CFP_ACC);

		/* Extract the address we are searching */
		index = reg >> XCESS_ADDR_SHIFT;
		index &= XCESS_ADDR_MASK;

		/* We have a valid search result, so flag it accordingly */
		if (reg & SEARCH_STS) {
			ret = bcm_sf2_cfp_rule_get(priv, port, nfc, true);
			if (ret)
				continue;

			rule_locs[rules_cnt] = index;
			rules_cnt++;
		}

		/* Search is over break out */
		if (!(reg & OP_STR_DONE))
			break;

	} while (index < priv->num_cfp_rules);

	/* Put the TCAM size here */
	nfc->data = bcm_sf2_cfp_rule_size(priv);
	nfc->rule_cnt = rules_cnt;

	return 0;
}

int bcm_sf2_get_rxnfc(struct dsa_switch *ds, int port,
		      struct ethtool_rxnfc *nfc, u32 *rule_locs)
{
	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
	int ret = 0;

	mutex_lock(&priv->cfp.lock);

	switch (nfc->cmd) {
	case ETHTOOL_GRXCLSRLCNT:
		/* Subtract the default, unusable rule */
		nfc->rule_cnt = bitmap_weight(priv->cfp.used,
					      priv->num_cfp_rules) - 1;
		/* We support specifying rule locations */
		nfc->data |= RX_CLS_LOC_SPECIAL;
		break;
	case ETHTOOL_GRXCLSRULE:
		ret = bcm_sf2_cfp_rule_get(priv, port, nfc, false);
		break;
	case ETHTOOL_GRXCLSRLALL:
		ret = bcm_sf2_cfp_rule_get_all(priv, port, nfc, rule_locs);
		break;
	default:
		ret = -EOPNOTSUPP;
		break;
	}

	mutex_unlock(&priv->cfp.lock);

	return ret;
}

int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port,
		      struct ethtool_rxnfc *nfc)
{
	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
	int ret = 0;

	mutex_lock(&priv->cfp.lock);

	switch (nfc->cmd) {
	case ETHTOOL_SRXCLSRLINS:
		ret = bcm_sf2_cfp_rule_set(ds, port, &nfc->fs);
		break;

	case ETHTOOL_SRXCLSRLDEL:
		ret = bcm_sf2_cfp_rule_del(priv, port, nfc->fs.location);
		break;
	default:
		ret = -EOPNOTSUPP;
		break;
	}

	mutex_unlock(&priv->cfp.lock);

	return ret;
}

int bcm_sf2_cfp_rst(struct bcm_sf2_priv *priv)
{
	unsigned int timeout = 1000;
	u32 reg;

	reg = core_readl(priv, CORE_CFP_ACC);
	reg |= TCAM_RESET;
	core_writel(priv, reg, CORE_CFP_ACC);

	do {
		reg = core_readl(priv, CORE_CFP_ACC);
		if (!(reg & TCAM_RESET))
			break;

		cpu_relax();
	} while (timeout--);

	if (!timeout)
		return -ETIMEDOUT;

	return 0;
}
