// SPDX-License-Identifier: GPL-2.0
/* Marvell RVU Admin Function driver
 *
 * Copyright (C) 2021 Marvell.
 *
 */

#include <linux/bitfield.h>
#include "rvu.h"

static void rvu_switch_enable_lbk_link(struct rvu *rvu, u16 pcifunc, bool enable)
{
	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
	struct nix_hw *nix_hw;

	nix_hw = get_nix_hw(rvu->hw, pfvf->nix_blkaddr);
	/* Enable LBK links with channel 63 for TX MCAM rule */
	rvu_nix_tx_tl2_cfg(rvu, pfvf->nix_blkaddr, pcifunc,
			   &nix_hw->txsch[NIX_TXSCH_LVL_TL2], enable);
}

static int rvu_switch_install_rx_rule(struct rvu *rvu, u16 pcifunc,
				      u16 chan_mask)
{
	struct npc_install_flow_req req = { 0 };
	struct npc_install_flow_rsp rsp = { 0 };
	struct rvu_pfvf *pfvf;

	pfvf = rvu_get_pfvf(rvu, pcifunc);
	/* If the pcifunc is not initialized then nothing to do.
	 * This same function will be called again via rvu_switch_update_rules
	 * after pcifunc is initialized.
	 */
	if (!test_bit(NIXLF_INITIALIZED, &pfvf->flags))
		return 0;

	ether_addr_copy(req.packet.dmac, pfvf->mac_addr);
	eth_broadcast_addr((u8 *)&req.mask.dmac);
	req.hdr.pcifunc = 0; /* AF is requester */
	req.vf = pcifunc;
	req.features = BIT_ULL(NPC_DMAC);
	req.channel = pfvf->rx_chan_base;
	req.chan_mask = chan_mask;
	req.intf = pfvf->nix_rx_intf;
	req.op = NIX_RX_ACTION_DEFAULT;
	req.default_rule = 1;

	return rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
}

static int rvu_switch_install_tx_rule(struct rvu *rvu, u16 pcifunc, u16 entry)
{
	struct npc_install_flow_req req = { 0 };
	struct npc_install_flow_rsp rsp = { 0 };
	struct rvu_pfvf *pfvf;
	u8 lbkid;

	pfvf = rvu_get_pfvf(rvu, pcifunc);
	/* If the pcifunc is not initialized then nothing to do.
	 * This same function will be called again via rvu_switch_update_rules
	 * after pcifunc is initialized.
	 */
	if (!test_bit(NIXLF_INITIALIZED, &pfvf->flags))
		return 0;

	rvu_switch_enable_lbk_link(rvu, pcifunc, true);

	lbkid = pfvf->nix_blkaddr == BLKADDR_NIX0 ? 0 : 1;
	ether_addr_copy(req.packet.dmac, pfvf->mac_addr);
	eth_broadcast_addr((u8 *)&req.mask.dmac);
	req.hdr.pcifunc = 0; /* AF is requester */
	req.vf = pcifunc;
	req.entry = entry;
	req.features = BIT_ULL(NPC_DMAC);
	req.intf = pfvf->nix_tx_intf;
	req.op = NIX_TX_ACTIONOP_UCAST_CHAN;
	req.index = (lbkid << 8) | RVU_SWITCH_LBK_CHAN;
	req.set_cntr = 1;

	return rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
}

static int rvu_switch_install_rules(struct rvu *rvu)
{
	struct rvu_switch *rswitch = &rvu->rswitch;
	u16 start = rswitch->start_entry;
	struct rvu_hwinfo *hw = rvu->hw;
	u16 pcifunc, entry = 0;
	int pf, vf, numvfs;
	int err;

	for (pf = 1; pf < hw->total_pfs; pf++) {
		if (!is_pf_cgxmapped(rvu, pf))
			continue;

		pcifunc = pf << 10;
		/* rvu_get_nix_blkaddr sets up the corresponding NIX block
		 * address and NIX RX and TX interfaces for a pcifunc.
		 * Generally it is called during attach call of a pcifunc but it
		 * is called here since we are pre-installing rules before
		 * nixlfs are attached
		 */
		rvu_get_nix_blkaddr(rvu, pcifunc);

		/* MCAM RX rule for a PF/VF already exists as default unicast
		 * rules installed by AF. Hence change the channel in those
		 * rules to ignore channel so that packets with the required
		 * DMAC received from LBK(by other PF/VFs in system) or from
		 * external world (from wire) are accepted.
		 */
		err = rvu_switch_install_rx_rule(rvu, pcifunc, 0x0);
		if (err) {
			dev_err(rvu->dev, "RX rule for PF%d failed(%d)\n",
				pf, err);
			return err;
		}

		err = rvu_switch_install_tx_rule(rvu, pcifunc, start + entry);
		if (err) {
			dev_err(rvu->dev, "TX rule for PF%d failed(%d)\n",
				pf, err);
			return err;
		}

		rswitch->entry2pcifunc[entry++] = pcifunc;

		rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL);
		for (vf = 0; vf < numvfs; vf++) {
			pcifunc = pf << 10 | ((vf + 1) & 0x3FF);
			rvu_get_nix_blkaddr(rvu, pcifunc);

			err = rvu_switch_install_rx_rule(rvu, pcifunc, 0x0);
			if (err) {
				dev_err(rvu->dev,
					"RX rule for PF%dVF%d failed(%d)\n",
					pf, vf, err);
				return err;
			}

			err = rvu_switch_install_tx_rule(rvu, pcifunc,
							 start + entry);
			if (err) {
				dev_err(rvu->dev,
					"TX rule for PF%dVF%d failed(%d)\n",
					pf, vf, err);
				return err;
			}

			rswitch->entry2pcifunc[entry++] = pcifunc;
		}
	}

	return 0;
}

void rvu_switch_enable(struct rvu *rvu)
{
	struct npc_mcam_alloc_entry_req alloc_req = { 0 };
	struct npc_mcam_alloc_entry_rsp alloc_rsp = { 0 };
	struct npc_delete_flow_req uninstall_req = { 0 };
	struct npc_delete_flow_rsp uninstall_rsp = { 0 };
	struct npc_mcam_free_entry_req free_req = { 0 };
	struct rvu_switch *rswitch = &rvu->rswitch;
	struct msg_rsp rsp;
	int ret;

	alloc_req.contig = true;
	alloc_req.count = rvu->cgx_mapped_pfs + rvu->cgx_mapped_vfs;
	ret = rvu_mbox_handler_npc_mcam_alloc_entry(rvu, &alloc_req,
						    &alloc_rsp);
	if (ret) {
		dev_err(rvu->dev,
			"Unable to allocate MCAM entries\n");
		goto exit;
	}

	if (alloc_rsp.count != alloc_req.count) {
		dev_err(rvu->dev,
			"Unable to allocate %d MCAM entries, got %d\n",
			alloc_req.count, alloc_rsp.count);
		goto free_entries;
	}

	rswitch->entry2pcifunc = kcalloc(alloc_req.count, sizeof(u16),
					 GFP_KERNEL);
	if (!rswitch->entry2pcifunc)
		goto free_entries;

	rswitch->used_entries = alloc_rsp.count;
	rswitch->start_entry = alloc_rsp.entry;

	ret = rvu_switch_install_rules(rvu);
	if (ret)
		goto uninstall_rules;

	return;

uninstall_rules:
	uninstall_req.start = rswitch->start_entry;
	uninstall_req.end =  rswitch->start_entry + rswitch->used_entries - 1;
	rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &uninstall_rsp);
	kfree(rswitch->entry2pcifunc);
free_entries:
	free_req.all = 1;
	rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp);
exit:
	return;
}

void rvu_switch_disable(struct rvu *rvu)
{
	struct npc_delete_flow_req uninstall_req = { 0 };
	struct npc_delete_flow_rsp uninstall_rsp = { 0 };
	struct npc_mcam_free_entry_req free_req = { 0 };
	struct rvu_switch *rswitch = &rvu->rswitch;
	struct rvu_hwinfo *hw = rvu->hw;
	int pf, vf, numvfs;
	struct msg_rsp rsp;
	u16 pcifunc;
	int err;

	if (!rswitch->used_entries)
		return;

	for (pf = 1; pf < hw->total_pfs; pf++) {
		if (!is_pf_cgxmapped(rvu, pf))
			continue;

		pcifunc = pf << 10;
		err = rvu_switch_install_rx_rule(rvu, pcifunc, 0xFFF);
		if (err)
			dev_err(rvu->dev,
				"Reverting RX rule for PF%d failed(%d)\n",
				pf, err);

		/* Disable LBK link */
		rvu_switch_enable_lbk_link(rvu, pcifunc, false);

		rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL);
		for (vf = 0; vf < numvfs; vf++) {
			pcifunc = pf << 10 | ((vf + 1) & 0x3FF);
			err = rvu_switch_install_rx_rule(rvu, pcifunc, 0xFFF);
			if (err)
				dev_err(rvu->dev,
					"Reverting RX rule for PF%dVF%d failed(%d)\n",
					pf, vf, err);

			rvu_switch_enable_lbk_link(rvu, pcifunc, false);
		}
	}

	uninstall_req.start = rswitch->start_entry;
	uninstall_req.end =  rswitch->start_entry + rswitch->used_entries - 1;
	free_req.all = 1;
	rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &uninstall_rsp);
	rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp);
	rswitch->used_entries = 0;
	kfree(rswitch->entry2pcifunc);
}

void rvu_switch_update_rules(struct rvu *rvu, u16 pcifunc)
{
	struct rvu_switch *rswitch = &rvu->rswitch;
	u32 max = rswitch->used_entries;
	u16 entry;

	if (!rswitch->used_entries)
		return;

	for (entry = 0; entry < max; entry++) {
		if (rswitch->entry2pcifunc[entry] == pcifunc)
			break;
	}

	if (entry >= max)
		return;

	rvu_switch_install_tx_rule(rvu, pcifunc, rswitch->start_entry + entry);
	rvu_switch_install_rx_rule(rvu, pcifunc, 0x0);
}
