brintos

brintos / linux-shallow public Read only

0
0
Text · 7.5 KiB · 854045e Raw
281 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Marvell RVU Admin Function driver3 *4 * Copyright (C) 2021 Marvell.5 *6 */7 8#include <linux/bitfield.h>9#include "rvu.h"10 11static void rvu_switch_enable_lbk_link(struct rvu *rvu, u16 pcifunc, bool enable)12{13	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);14	struct nix_hw *nix_hw;15 16	nix_hw = get_nix_hw(rvu->hw, pfvf->nix_blkaddr);17	/* Enable LBK links with channel 63 for TX MCAM rule */18	rvu_nix_tx_tl2_cfg(rvu, pfvf->nix_blkaddr, pcifunc,19			   &nix_hw->txsch[NIX_TXSCH_LVL_TL2], enable);20}21 22static int rvu_switch_install_rx_rule(struct rvu *rvu, u16 pcifunc,23				      u16 chan_mask)24{25	struct npc_install_flow_req req = { 0 };26	struct npc_install_flow_rsp rsp = { 0 };27	struct rvu_pfvf *pfvf;28 29	pfvf = rvu_get_pfvf(rvu, pcifunc);30	/* If the pcifunc is not initialized then nothing to do.31	 * This same function will be called again via rvu_switch_update_rules32	 * after pcifunc is initialized.33	 */34	if (!test_bit(NIXLF_INITIALIZED, &pfvf->flags))35		return 0;36 37	ether_addr_copy(req.packet.dmac, pfvf->mac_addr);38	eth_broadcast_addr((u8 *)&req.mask.dmac);39	req.hdr.pcifunc = 0; /* AF is requester */40	req.vf = pcifunc;41	req.features = BIT_ULL(NPC_DMAC);42	req.channel = pfvf->rx_chan_base;43	req.chan_mask = chan_mask;44	req.intf = pfvf->nix_rx_intf;45	req.op = NIX_RX_ACTION_DEFAULT;46	req.default_rule = 1;47 48	return rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);49}50 51static int rvu_switch_install_tx_rule(struct rvu *rvu, u16 pcifunc, u16 entry)52{53	struct npc_install_flow_req req = { 0 };54	struct npc_install_flow_rsp rsp = { 0 };55	struct rvu_pfvf *pfvf;56	u8 lbkid;57 58	pfvf = rvu_get_pfvf(rvu, pcifunc);59	/* If the pcifunc is not initialized then nothing to do.60	 * This same function will be called again via rvu_switch_update_rules61	 * after pcifunc is initialized.62	 */63	if (!test_bit(NIXLF_INITIALIZED, &pfvf->flags))64		return 0;65 66	rvu_switch_enable_lbk_link(rvu, pcifunc, true);67 68	lbkid = pfvf->nix_blkaddr == BLKADDR_NIX0 ? 0 : 1;69	ether_addr_copy(req.packet.dmac, pfvf->mac_addr);70	eth_broadcast_addr((u8 *)&req.mask.dmac);71	req.hdr.pcifunc = 0; /* AF is requester */72	req.vf = pcifunc;73	req.entry = entry;74	req.features = BIT_ULL(NPC_DMAC);75	req.intf = pfvf->nix_tx_intf;76	req.op = NIX_TX_ACTIONOP_UCAST_CHAN;77	req.index = (lbkid << 8) | RVU_SWITCH_LBK_CHAN;78	req.set_cntr = 1;79 80	return rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);81}82 83static int rvu_switch_install_rules(struct rvu *rvu)84{85	struct rvu_switch *rswitch = &rvu->rswitch;86	u16 start = rswitch->start_entry;87	struct rvu_hwinfo *hw = rvu->hw;88	u16 pcifunc, entry = 0;89	int pf, vf, numvfs;90	int err;91 92	for (pf = 1; pf < hw->total_pfs; pf++) {93		if (!is_pf_cgxmapped(rvu, pf))94			continue;95 96		pcifunc = pf << 10;97		/* rvu_get_nix_blkaddr sets up the corresponding NIX block98		 * address and NIX RX and TX interfaces for a pcifunc.99		 * Generally it is called during attach call of a pcifunc but it100		 * is called here since we are pre-installing rules before101		 * nixlfs are attached102		 */103		rvu_get_nix_blkaddr(rvu, pcifunc);104 105		/* MCAM RX rule for a PF/VF already exists as default unicast106		 * rules installed by AF. Hence change the channel in those107		 * rules to ignore channel so that packets with the required108		 * DMAC received from LBK(by other PF/VFs in system) or from109		 * external world (from wire) are accepted.110		 */111		err = rvu_switch_install_rx_rule(rvu, pcifunc, 0x0);112		if (err) {113			dev_err(rvu->dev, "RX rule for PF%d failed(%d)\n",114				pf, err);115			return err;116		}117 118		err = rvu_switch_install_tx_rule(rvu, pcifunc, start + entry);119		if (err) {120			dev_err(rvu->dev, "TX rule for PF%d failed(%d)\n",121				pf, err);122			return err;123		}124 125		rswitch->entry2pcifunc[entry++] = pcifunc;126 127		rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL);128		for (vf = 0; vf < numvfs; vf++) {129			pcifunc = pf << 10 | ((vf + 1) & 0x3FF);130			rvu_get_nix_blkaddr(rvu, pcifunc);131 132			err = rvu_switch_install_rx_rule(rvu, pcifunc, 0x0);133			if (err) {134				dev_err(rvu->dev,135					"RX rule for PF%dVF%d failed(%d)\n",136					pf, vf, err);137				return err;138			}139 140			err = rvu_switch_install_tx_rule(rvu, pcifunc,141							 start + entry);142			if (err) {143				dev_err(rvu->dev,144					"TX rule for PF%dVF%d failed(%d)\n",145					pf, vf, err);146				return err;147			}148 149			rswitch->entry2pcifunc[entry++] = pcifunc;150		}151	}152 153	return 0;154}155 156void rvu_switch_enable(struct rvu *rvu)157{158	struct npc_mcam_alloc_entry_req alloc_req = { 0 };159	struct npc_mcam_alloc_entry_rsp alloc_rsp = { 0 };160	struct npc_delete_flow_req uninstall_req = { 0 };161	struct npc_delete_flow_rsp uninstall_rsp = { 0 };162	struct npc_mcam_free_entry_req free_req = { 0 };163	struct rvu_switch *rswitch = &rvu->rswitch;164	struct msg_rsp rsp;165	int ret;166 167	alloc_req.contig = true;168	alloc_req.count = rvu->cgx_mapped_pfs + rvu->cgx_mapped_vfs;169	ret = rvu_mbox_handler_npc_mcam_alloc_entry(rvu, &alloc_req,170						    &alloc_rsp);171	if (ret) {172		dev_err(rvu->dev,173			"Unable to allocate MCAM entries\n");174		goto exit;175	}176 177	if (alloc_rsp.count != alloc_req.count) {178		dev_err(rvu->dev,179			"Unable to allocate %d MCAM entries, got %d\n",180			alloc_req.count, alloc_rsp.count);181		goto free_entries;182	}183 184	rswitch->entry2pcifunc = kcalloc(alloc_req.count, sizeof(u16),185					 GFP_KERNEL);186	if (!rswitch->entry2pcifunc)187		goto free_entries;188 189	rswitch->used_entries = alloc_rsp.count;190	rswitch->start_entry = alloc_rsp.entry;191 192	ret = rvu_switch_install_rules(rvu);193	if (ret)194		goto uninstall_rules;195 196	return;197 198uninstall_rules:199	uninstall_req.start = rswitch->start_entry;200	uninstall_req.end =  rswitch->start_entry + rswitch->used_entries - 1;201	rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &uninstall_rsp);202	kfree(rswitch->entry2pcifunc);203free_entries:204	free_req.all = 1;205	rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp);206exit:207	return;208}209 210void rvu_switch_disable(struct rvu *rvu)211{212	struct npc_delete_flow_req uninstall_req = { 0 };213	struct npc_delete_flow_rsp uninstall_rsp = { 0 };214	struct npc_mcam_free_entry_req free_req = { 0 };215	struct rvu_switch *rswitch = &rvu->rswitch;216	struct rvu_hwinfo *hw = rvu->hw;217	int pf, vf, numvfs;218	struct msg_rsp rsp;219	u16 pcifunc;220	int err;221 222	if (!rswitch->used_entries)223		return;224 225	for (pf = 1; pf < hw->total_pfs; pf++) {226		if (!is_pf_cgxmapped(rvu, pf))227			continue;228 229		pcifunc = pf << 10;230		err = rvu_switch_install_rx_rule(rvu, pcifunc, 0xFFF);231		if (err)232			dev_err(rvu->dev,233				"Reverting RX rule for PF%d failed(%d)\n",234				pf, err);235 236		/* Disable LBK link */237		rvu_switch_enable_lbk_link(rvu, pcifunc, false);238 239		rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL);240		for (vf = 0; vf < numvfs; vf++) {241			pcifunc = pf << 10 | ((vf + 1) & 0x3FF);242			err = rvu_switch_install_rx_rule(rvu, pcifunc, 0xFFF);243			if (err)244				dev_err(rvu->dev,245					"Reverting RX rule for PF%dVF%d failed(%d)\n",246					pf, vf, err);247 248			rvu_switch_enable_lbk_link(rvu, pcifunc, false);249		}250	}251 252	uninstall_req.start = rswitch->start_entry;253	uninstall_req.end =  rswitch->start_entry + rswitch->used_entries - 1;254	free_req.all = 1;255	rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &uninstall_rsp);256	rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp);257	rswitch->used_entries = 0;258	kfree(rswitch->entry2pcifunc);259}260 261void rvu_switch_update_rules(struct rvu *rvu, u16 pcifunc)262{263	struct rvu_switch *rswitch = &rvu->rswitch;264	u32 max = rswitch->used_entries;265	u16 entry;266 267	if (!rswitch->used_entries)268		return;269 270	for (entry = 0; entry < max; entry++) {271		if (rswitch->entry2pcifunc[entry] == pcifunc)272			break;273	}274 275	if (entry >= max)276		return;277 278	rvu_switch_install_tx_rule(rvu, pcifunc, rswitch->start_entry + entry);279	rvu_switch_install_rx_rule(rvu, pcifunc, 0x0);280}281