// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/* Microsemi Ocelot Switch driver
 *
 * Copyright (c) 2017, 2019 Microsemi Corporation
 * Copyright 2020-2021 NXP
 */

#include <linux/if_bridge.h>
#include <linux/mrp_bridge.h>
#include <soc/mscc/ocelot_vcap.h>
#include <uapi/linux/mrp_bridge.h>
#include "ocelot.h"
#include "ocelot_vcap.h"

static const u8 mrp_test_dmac[] = { 0x01, 0x15, 0x4e, 0x00, 0x00, 0x01 };
static const u8 mrp_control_dmac[] = { 0x01, 0x15, 0x4e, 0x00, 0x00, 0x02 };

static int ocelot_mrp_find_partner_port(struct ocelot *ocelot,
					struct ocelot_port *p)
{
	int i;

	for (i = 0; i < ocelot->num_phys_ports; ++i) {
		struct ocelot_port *ocelot_port = ocelot->ports[i];

		if (!ocelot_port || p == ocelot_port)
			continue;

		if (ocelot_port->mrp_ring_id == p->mrp_ring_id)
			return i;
	}

	return -1;
}

static int ocelot_mrp_del_vcap(struct ocelot *ocelot, int id)
{
	struct ocelot_vcap_block *block_vcap_is2;
	struct ocelot_vcap_filter *filter;

	block_vcap_is2 = &ocelot->block[VCAP_IS2];
	filter = ocelot_vcap_block_find_filter_by_id(block_vcap_is2, id,
						     false);
	if (!filter)
		return 0;

	return ocelot_vcap_filter_del(ocelot, filter);
}

static int ocelot_mrp_redirect_add_vcap(struct ocelot *ocelot, int src_port,
					int dst_port)
{
	const u8 mrp_test_mask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
	struct ocelot_vcap_filter *filter;
	int err;

	filter = kzalloc(sizeof(*filter), GFP_KERNEL);
	if (!filter)
		return -ENOMEM;

	filter->key_type = OCELOT_VCAP_KEY_ETYPE;
	filter->prio = 1;
	filter->id.cookie = src_port;
	filter->id.tc_offload = false;
	filter->block_id = VCAP_IS2;
	filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
	filter->ingress_port_mask = BIT(src_port);
	ether_addr_copy(filter->key.etype.dmac.value, mrp_test_dmac);
	ether_addr_copy(filter->key.etype.dmac.mask, mrp_test_mask);
	filter->action.mask_mode = OCELOT_MASK_MODE_REDIRECT;
	filter->action.port_mask = BIT(dst_port);

	err = ocelot_vcap_filter_add(ocelot, filter, NULL);
	if (err)
		kfree(filter);

	return err;
}

static int ocelot_mrp_copy_add_vcap(struct ocelot *ocelot, int port,
				    int prio, unsigned long cookie)
{
	const u8 mrp_mask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
	struct ocelot_vcap_filter *filter;
	int err;

	filter = kzalloc(sizeof(*filter), GFP_KERNEL);
	if (!filter)
		return -ENOMEM;

	filter->key_type = OCELOT_VCAP_KEY_ETYPE;
	filter->prio = prio;
	filter->id.cookie = cookie;
	filter->id.tc_offload = false;
	filter->block_id = VCAP_IS2;
	filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
	filter->ingress_port_mask = BIT(port);
	/* Here is possible to use control or test dmac because the mask
	 * doesn't cover the LSB
	 */
	ether_addr_copy(filter->key.etype.dmac.value, mrp_test_dmac);
	ether_addr_copy(filter->key.etype.dmac.mask, mrp_mask);
	filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
	filter->action.port_mask = 0x0;
	filter->action.cpu_copy_ena = true;
	filter->action.cpu_qu_num = OCELOT_MRP_CPUQ;

	err = ocelot_vcap_filter_add(ocelot, filter, NULL);
	if (err)
		kfree(filter);

	return err;
}

static void ocelot_mrp_save_mac(struct ocelot *ocelot,
				struct ocelot_port *port)
{
	ocelot_mact_learn(ocelot, PGID_BLACKHOLE, mrp_test_dmac,
			  OCELOT_VLAN_UNAWARE_PVID, ENTRYTYPE_LOCKED);
	ocelot_mact_learn(ocelot, PGID_BLACKHOLE, mrp_control_dmac,
			  OCELOT_VLAN_UNAWARE_PVID, ENTRYTYPE_LOCKED);
}

static void ocelot_mrp_del_mac(struct ocelot *ocelot,
			       struct ocelot_port *port)
{
	ocelot_mact_forget(ocelot, mrp_test_dmac, OCELOT_VLAN_UNAWARE_PVID);
	ocelot_mact_forget(ocelot, mrp_control_dmac, OCELOT_VLAN_UNAWARE_PVID);
}

int ocelot_mrp_add(struct ocelot *ocelot, int port,
		   const struct switchdev_obj_mrp *mrp)
{
	struct ocelot_port *ocelot_port = ocelot->ports[port];
	struct ocelot_port_private *priv;
	struct net_device *dev;

	if (!ocelot_port)
		return -EOPNOTSUPP;

	priv = container_of(ocelot_port, struct ocelot_port_private, port);
	dev = priv->dev;

	if (mrp->p_port != dev && mrp->s_port != dev)
		return 0;

	ocelot_port->mrp_ring_id = mrp->ring_id;

	return 0;
}
EXPORT_SYMBOL(ocelot_mrp_add);

int ocelot_mrp_del(struct ocelot *ocelot, int port,
		   const struct switchdev_obj_mrp *mrp)
{
	struct ocelot_port *ocelot_port = ocelot->ports[port];

	if (!ocelot_port)
		return -EOPNOTSUPP;

	if (ocelot_port->mrp_ring_id != mrp->ring_id)
		return 0;

	ocelot_port->mrp_ring_id = 0;

	return 0;
}
EXPORT_SYMBOL(ocelot_mrp_del);

int ocelot_mrp_add_ring_role(struct ocelot *ocelot, int port,
			     const struct switchdev_obj_ring_role_mrp *mrp)
{
	struct ocelot_port *ocelot_port = ocelot->ports[port];
	int dst_port;
	int err;

	if (!ocelot_port)
		return -EOPNOTSUPP;

	if (mrp->ring_role != BR_MRP_RING_ROLE_MRC && !mrp->sw_backup)
		return -EOPNOTSUPP;

	if (ocelot_port->mrp_ring_id != mrp->ring_id)
		return 0;

	ocelot_mrp_save_mac(ocelot, ocelot_port);

	if (mrp->ring_role != BR_MRP_RING_ROLE_MRC)
		return ocelot_mrp_copy_add_vcap(ocelot, port, 1, port);

	dst_port = ocelot_mrp_find_partner_port(ocelot, ocelot_port);
	if (dst_port == -1)
		return -EINVAL;

	err = ocelot_mrp_redirect_add_vcap(ocelot, port, dst_port);
	if (err)
		return err;

	err = ocelot_mrp_copy_add_vcap(ocelot, port, 2,
				       port + ocelot->num_phys_ports);
	if (err) {
		ocelot_mrp_del_vcap(ocelot, port);
		return err;
	}

	return 0;
}
EXPORT_SYMBOL(ocelot_mrp_add_ring_role);

int ocelot_mrp_del_ring_role(struct ocelot *ocelot, int port,
			     const struct switchdev_obj_ring_role_mrp *mrp)
{
	struct ocelot_port *ocelot_port = ocelot->ports[port];
	int i;

	if (!ocelot_port)
		return -EOPNOTSUPP;

	if (mrp->ring_role != BR_MRP_RING_ROLE_MRC && !mrp->sw_backup)
		return -EOPNOTSUPP;

	if (ocelot_port->mrp_ring_id != mrp->ring_id)
		return 0;

	ocelot_mrp_del_vcap(ocelot, port);
	ocelot_mrp_del_vcap(ocelot, port + ocelot->num_phys_ports);

	for (i = 0; i < ocelot->num_phys_ports; ++i) {
		ocelot_port = ocelot->ports[i];

		if (!ocelot_port)
			continue;

		if (ocelot_port->mrp_ring_id != 0)
			goto out;
	}

	ocelot_mrp_del_mac(ocelot, ocelot->ports[port]);
out:
	return 0;
}
EXPORT_SYMBOL(ocelot_mrp_del_ring_role);
