xref: /openbmc/linux/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
123109f8dSSubbaraya Sundeep // SPDX-License-Identifier: GPL-2.0
2c7cd6c5aSSunil Goutham /* Marvell RVU Admin Function driver
323109f8dSSubbaraya Sundeep  *
423109f8dSSubbaraya Sundeep  * Copyright (C) 2021 Marvell.
5c7cd6c5aSSunil Goutham  *
623109f8dSSubbaraya Sundeep  */
723109f8dSSubbaraya Sundeep 
823109f8dSSubbaraya Sundeep #include <linux/bitfield.h>
923109f8dSSubbaraya Sundeep #include "rvu.h"
1023109f8dSSubbaraya Sundeep 
rvu_switch_enable_lbk_link(struct rvu * rvu,u16 pcifunc,bool enable)11b6a072a1SSubbaraya Sundeep static void rvu_switch_enable_lbk_link(struct rvu *rvu, u16 pcifunc, bool enable)
12b6a072a1SSubbaraya Sundeep {
13b6a072a1SSubbaraya Sundeep 	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
14b6a072a1SSubbaraya Sundeep 	struct nix_hw *nix_hw;
15b6a072a1SSubbaraya Sundeep 
16b6a072a1SSubbaraya Sundeep 	nix_hw = get_nix_hw(rvu->hw, pfvf->nix_blkaddr);
17b6a072a1SSubbaraya Sundeep 	/* Enable LBK links with channel 63 for TX MCAM rule */
18b6a072a1SSubbaraya Sundeep 	rvu_nix_tx_tl2_cfg(rvu, pfvf->nix_blkaddr, pcifunc,
19b6a072a1SSubbaraya Sundeep 			   &nix_hw->txsch[NIX_TXSCH_LVL_TL2], enable);
20b6a072a1SSubbaraya Sundeep }
21b6a072a1SSubbaraya Sundeep 
rvu_switch_install_rx_rule(struct rvu * rvu,u16 pcifunc,u16 chan_mask)2223109f8dSSubbaraya Sundeep static int rvu_switch_install_rx_rule(struct rvu *rvu, u16 pcifunc,
2323109f8dSSubbaraya Sundeep 				      u16 chan_mask)
2423109f8dSSubbaraya Sundeep {
2523109f8dSSubbaraya Sundeep 	struct npc_install_flow_req req = { 0 };
2623109f8dSSubbaraya Sundeep 	struct npc_install_flow_rsp rsp = { 0 };
2723109f8dSSubbaraya Sundeep 	struct rvu_pfvf *pfvf;
2823109f8dSSubbaraya Sundeep 
2923109f8dSSubbaraya Sundeep 	pfvf = rvu_get_pfvf(rvu, pcifunc);
3023109f8dSSubbaraya Sundeep 	/* If the pcifunc is not initialized then nothing to do.
3123109f8dSSubbaraya Sundeep 	 * This same function will be called again via rvu_switch_update_rules
3223109f8dSSubbaraya Sundeep 	 * after pcifunc is initialized.
3323109f8dSSubbaraya Sundeep 	 */
3423109f8dSSubbaraya Sundeep 	if (!test_bit(NIXLF_INITIALIZED, &pfvf->flags))
3523109f8dSSubbaraya Sundeep 		return 0;
3623109f8dSSubbaraya Sundeep 
3723109f8dSSubbaraya Sundeep 	ether_addr_copy(req.packet.dmac, pfvf->mac_addr);
3823109f8dSSubbaraya Sundeep 	eth_broadcast_addr((u8 *)&req.mask.dmac);
3923109f8dSSubbaraya Sundeep 	req.hdr.pcifunc = 0; /* AF is requester */
4023109f8dSSubbaraya Sundeep 	req.vf = pcifunc;
4123109f8dSSubbaraya Sundeep 	req.features = BIT_ULL(NPC_DMAC);
4223109f8dSSubbaraya Sundeep 	req.channel = pfvf->rx_chan_base;
4323109f8dSSubbaraya Sundeep 	req.chan_mask = chan_mask;
4423109f8dSSubbaraya Sundeep 	req.intf = pfvf->nix_rx_intf;
4523109f8dSSubbaraya Sundeep 	req.op = NIX_RX_ACTION_DEFAULT;
4623109f8dSSubbaraya Sundeep 	req.default_rule = 1;
4723109f8dSSubbaraya Sundeep 
4823109f8dSSubbaraya Sundeep 	return rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
4923109f8dSSubbaraya Sundeep }
5023109f8dSSubbaraya Sundeep 
rvu_switch_install_tx_rule(struct rvu * rvu,u16 pcifunc,u16 entry)5123109f8dSSubbaraya Sundeep static int rvu_switch_install_tx_rule(struct rvu *rvu, u16 pcifunc, u16 entry)
5223109f8dSSubbaraya Sundeep {
5323109f8dSSubbaraya Sundeep 	struct npc_install_flow_req req = { 0 };
5423109f8dSSubbaraya Sundeep 	struct npc_install_flow_rsp rsp = { 0 };
5523109f8dSSubbaraya Sundeep 	struct rvu_pfvf *pfvf;
5623109f8dSSubbaraya Sundeep 	u8 lbkid;
5723109f8dSSubbaraya Sundeep 
5823109f8dSSubbaraya Sundeep 	pfvf = rvu_get_pfvf(rvu, pcifunc);
5923109f8dSSubbaraya Sundeep 	/* If the pcifunc is not initialized then nothing to do.
6023109f8dSSubbaraya Sundeep 	 * This same function will be called again via rvu_switch_update_rules
6123109f8dSSubbaraya Sundeep 	 * after pcifunc is initialized.
6223109f8dSSubbaraya Sundeep 	 */
6323109f8dSSubbaraya Sundeep 	if (!test_bit(NIXLF_INITIALIZED, &pfvf->flags))
6423109f8dSSubbaraya Sundeep 		return 0;
6523109f8dSSubbaraya Sundeep 
66b6a072a1SSubbaraya Sundeep 	rvu_switch_enable_lbk_link(rvu, pcifunc, true);
67b6a072a1SSubbaraya Sundeep 
6823109f8dSSubbaraya Sundeep 	lbkid = pfvf->nix_blkaddr == BLKADDR_NIX0 ? 0 : 1;
6923109f8dSSubbaraya Sundeep 	ether_addr_copy(req.packet.dmac, pfvf->mac_addr);
7023109f8dSSubbaraya Sundeep 	eth_broadcast_addr((u8 *)&req.mask.dmac);
7123109f8dSSubbaraya Sundeep 	req.hdr.pcifunc = 0; /* AF is requester */
7223109f8dSSubbaraya Sundeep 	req.vf = pcifunc;
7323109f8dSSubbaraya Sundeep 	req.entry = entry;
7423109f8dSSubbaraya Sundeep 	req.features = BIT_ULL(NPC_DMAC);
7523109f8dSSubbaraya Sundeep 	req.intf = pfvf->nix_tx_intf;
7623109f8dSSubbaraya Sundeep 	req.op = NIX_TX_ACTIONOP_UCAST_CHAN;
7723109f8dSSubbaraya Sundeep 	req.index = (lbkid << 8) | RVU_SWITCH_LBK_CHAN;
7823109f8dSSubbaraya Sundeep 	req.set_cntr = 1;
7923109f8dSSubbaraya Sundeep 
8023109f8dSSubbaraya Sundeep 	return rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
8123109f8dSSubbaraya Sundeep }
8223109f8dSSubbaraya Sundeep 
rvu_switch_install_rules(struct rvu * rvu)8323109f8dSSubbaraya Sundeep static int rvu_switch_install_rules(struct rvu *rvu)
8423109f8dSSubbaraya Sundeep {
8523109f8dSSubbaraya Sundeep 	struct rvu_switch *rswitch = &rvu->rswitch;
8623109f8dSSubbaraya Sundeep 	u16 start = rswitch->start_entry;
8723109f8dSSubbaraya Sundeep 	struct rvu_hwinfo *hw = rvu->hw;
8823109f8dSSubbaraya Sundeep 	u16 pcifunc, entry = 0;
899986066dSSubbaraya Sundeep 	int pf, vf, numvfs;
9023109f8dSSubbaraya Sundeep 	int err;
9123109f8dSSubbaraya Sundeep 
9223109f8dSSubbaraya Sundeep 	for (pf = 1; pf < hw->total_pfs; pf++) {
9323109f8dSSubbaraya Sundeep 		if (!is_pf_cgxmapped(rvu, pf))
9423109f8dSSubbaraya Sundeep 			continue;
9523109f8dSSubbaraya Sundeep 
9623109f8dSSubbaraya Sundeep 		pcifunc = pf << 10;
9723109f8dSSubbaraya Sundeep 		/* rvu_get_nix_blkaddr sets up the corresponding NIX block
9823109f8dSSubbaraya Sundeep 		 * address and NIX RX and TX interfaces for a pcifunc.
9923109f8dSSubbaraya Sundeep 		 * Generally it is called during attach call of a pcifunc but it
10023109f8dSSubbaraya Sundeep 		 * is called here since we are pre-installing rules before
10123109f8dSSubbaraya Sundeep 		 * nixlfs are attached
10223109f8dSSubbaraya Sundeep 		 */
10323109f8dSSubbaraya Sundeep 		rvu_get_nix_blkaddr(rvu, pcifunc);
10423109f8dSSubbaraya Sundeep 
10523109f8dSSubbaraya Sundeep 		/* MCAM RX rule for a PF/VF already exists as default unicast
10623109f8dSSubbaraya Sundeep 		 * rules installed by AF. Hence change the channel in those
10723109f8dSSubbaraya Sundeep 		 * rules to ignore channel so that packets with the required
10823109f8dSSubbaraya Sundeep 		 * DMAC received from LBK(by other PF/VFs in system) or from
10923109f8dSSubbaraya Sundeep 		 * external world (from wire) are accepted.
11023109f8dSSubbaraya Sundeep 		 */
11123109f8dSSubbaraya Sundeep 		err = rvu_switch_install_rx_rule(rvu, pcifunc, 0x0);
11223109f8dSSubbaraya Sundeep 		if (err) {
11323109f8dSSubbaraya Sundeep 			dev_err(rvu->dev, "RX rule for PF%d failed(%d)\n",
11423109f8dSSubbaraya Sundeep 				pf, err);
11523109f8dSSubbaraya Sundeep 			return err;
11623109f8dSSubbaraya Sundeep 		}
11723109f8dSSubbaraya Sundeep 
11823109f8dSSubbaraya Sundeep 		err = rvu_switch_install_tx_rule(rvu, pcifunc, start + entry);
11923109f8dSSubbaraya Sundeep 		if (err) {
12023109f8dSSubbaraya Sundeep 			dev_err(rvu->dev, "TX rule for PF%d failed(%d)\n",
12123109f8dSSubbaraya Sundeep 				pf, err);
12223109f8dSSubbaraya Sundeep 			return err;
12323109f8dSSubbaraya Sundeep 		}
12423109f8dSSubbaraya Sundeep 
12523109f8dSSubbaraya Sundeep 		rswitch->entry2pcifunc[entry++] = pcifunc;
12623109f8dSSubbaraya Sundeep 
1279986066dSSubbaraya Sundeep 		rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL);
1289986066dSSubbaraya Sundeep 		for (vf = 0; vf < numvfs; vf++) {
12923109f8dSSubbaraya Sundeep 			pcifunc = pf << 10 | ((vf + 1) & 0x3FF);
13023109f8dSSubbaraya Sundeep 			rvu_get_nix_blkaddr(rvu, pcifunc);
13123109f8dSSubbaraya Sundeep 
13223109f8dSSubbaraya Sundeep 			err = rvu_switch_install_rx_rule(rvu, pcifunc, 0x0);
13323109f8dSSubbaraya Sundeep 			if (err) {
13423109f8dSSubbaraya Sundeep 				dev_err(rvu->dev,
13523109f8dSSubbaraya Sundeep 					"RX rule for PF%dVF%d failed(%d)\n",
13623109f8dSSubbaraya Sundeep 					pf, vf, err);
13723109f8dSSubbaraya Sundeep 				return err;
13823109f8dSSubbaraya Sundeep 			}
13923109f8dSSubbaraya Sundeep 
14023109f8dSSubbaraya Sundeep 			err = rvu_switch_install_tx_rule(rvu, pcifunc,
14123109f8dSSubbaraya Sundeep 							 start + entry);
14223109f8dSSubbaraya Sundeep 			if (err) {
14323109f8dSSubbaraya Sundeep 				dev_err(rvu->dev,
14423109f8dSSubbaraya Sundeep 					"TX rule for PF%dVF%d failed(%d)\n",
14523109f8dSSubbaraya Sundeep 					pf, vf, err);
14623109f8dSSubbaraya Sundeep 				return err;
14723109f8dSSubbaraya Sundeep 			}
14823109f8dSSubbaraya Sundeep 
14923109f8dSSubbaraya Sundeep 			rswitch->entry2pcifunc[entry++] = pcifunc;
15023109f8dSSubbaraya Sundeep 		}
15123109f8dSSubbaraya Sundeep 	}
15223109f8dSSubbaraya Sundeep 
15323109f8dSSubbaraya Sundeep 	return 0;
15423109f8dSSubbaraya Sundeep }
15523109f8dSSubbaraya Sundeep 
rvu_switch_enable(struct rvu * rvu)15623109f8dSSubbaraya Sundeep void rvu_switch_enable(struct rvu *rvu)
15723109f8dSSubbaraya Sundeep {
15823109f8dSSubbaraya Sundeep 	struct npc_mcam_alloc_entry_req alloc_req = { 0 };
15923109f8dSSubbaraya Sundeep 	struct npc_mcam_alloc_entry_rsp alloc_rsp = { 0 };
16023109f8dSSubbaraya Sundeep 	struct npc_delete_flow_req uninstall_req = { 0 };
161*ec87f054SSuman Ghosh 	struct npc_delete_flow_rsp uninstall_rsp = { 0 };
16223109f8dSSubbaraya Sundeep 	struct npc_mcam_free_entry_req free_req = { 0 };
16323109f8dSSubbaraya Sundeep 	struct rvu_switch *rswitch = &rvu->rswitch;
16423109f8dSSubbaraya Sundeep 	struct msg_rsp rsp;
16523109f8dSSubbaraya Sundeep 	int ret;
16623109f8dSSubbaraya Sundeep 
16723109f8dSSubbaraya Sundeep 	alloc_req.contig = true;
16823109f8dSSubbaraya Sundeep 	alloc_req.count = rvu->cgx_mapped_pfs + rvu->cgx_mapped_vfs;
16923109f8dSSubbaraya Sundeep 	ret = rvu_mbox_handler_npc_mcam_alloc_entry(rvu, &alloc_req,
17023109f8dSSubbaraya Sundeep 						    &alloc_rsp);
17123109f8dSSubbaraya Sundeep 	if (ret) {
17223109f8dSSubbaraya Sundeep 		dev_err(rvu->dev,
17323109f8dSSubbaraya Sundeep 			"Unable to allocate MCAM entries\n");
17423109f8dSSubbaraya Sundeep 		goto exit;
17523109f8dSSubbaraya Sundeep 	}
17623109f8dSSubbaraya Sundeep 
17723109f8dSSubbaraya Sundeep 	if (alloc_rsp.count != alloc_req.count) {
17823109f8dSSubbaraya Sundeep 		dev_err(rvu->dev,
17923109f8dSSubbaraya Sundeep 			"Unable to allocate %d MCAM entries, got %d\n",
18023109f8dSSubbaraya Sundeep 			alloc_req.count, alloc_rsp.count);
18123109f8dSSubbaraya Sundeep 		goto free_entries;
18223109f8dSSubbaraya Sundeep 	}
18323109f8dSSubbaraya Sundeep 
18423109f8dSSubbaraya Sundeep 	rswitch->entry2pcifunc = kcalloc(alloc_req.count, sizeof(u16),
18523109f8dSSubbaraya Sundeep 					 GFP_KERNEL);
18623109f8dSSubbaraya Sundeep 	if (!rswitch->entry2pcifunc)
18723109f8dSSubbaraya Sundeep 		goto free_entries;
18823109f8dSSubbaraya Sundeep 
18923109f8dSSubbaraya Sundeep 	rswitch->used_entries = alloc_rsp.count;
19023109f8dSSubbaraya Sundeep 	rswitch->start_entry = alloc_rsp.entry;
19123109f8dSSubbaraya Sundeep 
19223109f8dSSubbaraya Sundeep 	ret = rvu_switch_install_rules(rvu);
19323109f8dSSubbaraya Sundeep 	if (ret)
19423109f8dSSubbaraya Sundeep 		goto uninstall_rules;
19523109f8dSSubbaraya Sundeep 
19623109f8dSSubbaraya Sundeep 	return;
19723109f8dSSubbaraya Sundeep 
19823109f8dSSubbaraya Sundeep uninstall_rules:
19923109f8dSSubbaraya Sundeep 	uninstall_req.start = rswitch->start_entry;
20023109f8dSSubbaraya Sundeep 	uninstall_req.end =  rswitch->start_entry + rswitch->used_entries - 1;
201*ec87f054SSuman Ghosh 	rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &uninstall_rsp);
20223109f8dSSubbaraya Sundeep 	kfree(rswitch->entry2pcifunc);
20323109f8dSSubbaraya Sundeep free_entries:
20423109f8dSSubbaraya Sundeep 	free_req.all = 1;
20523109f8dSSubbaraya Sundeep 	rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp);
20623109f8dSSubbaraya Sundeep exit:
20723109f8dSSubbaraya Sundeep 	return;
20823109f8dSSubbaraya Sundeep }
20923109f8dSSubbaraya Sundeep 
rvu_switch_disable(struct rvu * rvu)21023109f8dSSubbaraya Sundeep void rvu_switch_disable(struct rvu *rvu)
21123109f8dSSubbaraya Sundeep {
21223109f8dSSubbaraya Sundeep 	struct npc_delete_flow_req uninstall_req = { 0 };
213*ec87f054SSuman Ghosh 	struct npc_delete_flow_rsp uninstall_rsp = { 0 };
21423109f8dSSubbaraya Sundeep 	struct npc_mcam_free_entry_req free_req = { 0 };
21523109f8dSSubbaraya Sundeep 	struct rvu_switch *rswitch = &rvu->rswitch;
21623109f8dSSubbaraya Sundeep 	struct rvu_hwinfo *hw = rvu->hw;
2179986066dSSubbaraya Sundeep 	int pf, vf, numvfs;
21823109f8dSSubbaraya Sundeep 	struct msg_rsp rsp;
21923109f8dSSubbaraya Sundeep 	u16 pcifunc;
22023109f8dSSubbaraya Sundeep 	int err;
22123109f8dSSubbaraya Sundeep 
22223109f8dSSubbaraya Sundeep 	if (!rswitch->used_entries)
22323109f8dSSubbaraya Sundeep 		return;
22423109f8dSSubbaraya Sundeep 
22523109f8dSSubbaraya Sundeep 	for (pf = 1; pf < hw->total_pfs; pf++) {
22623109f8dSSubbaraya Sundeep 		if (!is_pf_cgxmapped(rvu, pf))
22723109f8dSSubbaraya Sundeep 			continue;
22823109f8dSSubbaraya Sundeep 
22923109f8dSSubbaraya Sundeep 		pcifunc = pf << 10;
23023109f8dSSubbaraya Sundeep 		err = rvu_switch_install_rx_rule(rvu, pcifunc, 0xFFF);
23123109f8dSSubbaraya Sundeep 		if (err)
23223109f8dSSubbaraya Sundeep 			dev_err(rvu->dev,
23323109f8dSSubbaraya Sundeep 				"Reverting RX rule for PF%d failed(%d)\n",
23423109f8dSSubbaraya Sundeep 				pf, err);
23523109f8dSSubbaraya Sundeep 
236b6a072a1SSubbaraya Sundeep 		/* Disable LBK link */
237b6a072a1SSubbaraya Sundeep 		rvu_switch_enable_lbk_link(rvu, pcifunc, false);
238b6a072a1SSubbaraya Sundeep 
2399986066dSSubbaraya Sundeep 		rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL);
2409986066dSSubbaraya Sundeep 		for (vf = 0; vf < numvfs; vf++) {
24123109f8dSSubbaraya Sundeep 			pcifunc = pf << 10 | ((vf + 1) & 0x3FF);
24223109f8dSSubbaraya Sundeep 			err = rvu_switch_install_rx_rule(rvu, pcifunc, 0xFFF);
24323109f8dSSubbaraya Sundeep 			if (err)
24423109f8dSSubbaraya Sundeep 				dev_err(rvu->dev,
24523109f8dSSubbaraya Sundeep 					"Reverting RX rule for PF%dVF%d failed(%d)\n",
24623109f8dSSubbaraya Sundeep 					pf, vf, err);
247b6a072a1SSubbaraya Sundeep 
248b6a072a1SSubbaraya Sundeep 			rvu_switch_enable_lbk_link(rvu, pcifunc, false);
24923109f8dSSubbaraya Sundeep 		}
25023109f8dSSubbaraya Sundeep 	}
25123109f8dSSubbaraya Sundeep 
25223109f8dSSubbaraya Sundeep 	uninstall_req.start = rswitch->start_entry;
25323109f8dSSubbaraya Sundeep 	uninstall_req.end =  rswitch->start_entry + rswitch->used_entries - 1;
25423109f8dSSubbaraya Sundeep 	free_req.all = 1;
255*ec87f054SSuman Ghosh 	rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &uninstall_rsp);
25623109f8dSSubbaraya Sundeep 	rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp);
25723109f8dSSubbaraya Sundeep 	rswitch->used_entries = 0;
25823109f8dSSubbaraya Sundeep 	kfree(rswitch->entry2pcifunc);
25923109f8dSSubbaraya Sundeep }
26023109f8dSSubbaraya Sundeep 
rvu_switch_update_rules(struct rvu * rvu,u16 pcifunc)26123109f8dSSubbaraya Sundeep void rvu_switch_update_rules(struct rvu *rvu, u16 pcifunc)
26223109f8dSSubbaraya Sundeep {
26323109f8dSSubbaraya Sundeep 	struct rvu_switch *rswitch = &rvu->rswitch;
26423109f8dSSubbaraya Sundeep 	u32 max = rswitch->used_entries;
26523109f8dSSubbaraya Sundeep 	u16 entry;
26623109f8dSSubbaraya Sundeep 
26723109f8dSSubbaraya Sundeep 	if (!rswitch->used_entries)
26823109f8dSSubbaraya Sundeep 		return;
26923109f8dSSubbaraya Sundeep 
27023109f8dSSubbaraya Sundeep 	for (entry = 0; entry < max; entry++) {
27123109f8dSSubbaraya Sundeep 		if (rswitch->entry2pcifunc[entry] == pcifunc)
27223109f8dSSubbaraya Sundeep 			break;
27323109f8dSSubbaraya Sundeep 	}
27423109f8dSSubbaraya Sundeep 
27523109f8dSSubbaraya Sundeep 	if (entry >= max)
27623109f8dSSubbaraya Sundeep 		return;
27723109f8dSSubbaraya Sundeep 
27823109f8dSSubbaraya Sundeep 	rvu_switch_install_tx_rule(rvu, pcifunc, rswitch->start_entry + entry);
27923109f8dSSubbaraya Sundeep 	rvu_switch_install_rx_rule(rvu, pcifunc, 0x0);
28023109f8dSSubbaraya Sundeep }
281