xref: /linux/drivers/net/ethernet/marvell/octeontx2/af/rvu_rep.c (revision c771600c6af14749609b49565ffb4cac2959710d)
1222a4eeaSGeetha sowjanya // SPDX-License-Identifier: GPL-2.0
2222a4eeaSGeetha sowjanya /* Marvell RVU Admin Function driver
3222a4eeaSGeetha sowjanya  *
4222a4eeaSGeetha sowjanya  * Copyright (C) 2024 Marvell.
5222a4eeaSGeetha sowjanya  *
6222a4eeaSGeetha sowjanya  */
7222a4eeaSGeetha sowjanya 
8222a4eeaSGeetha sowjanya #include <linux/bitfield.h>
9222a4eeaSGeetha sowjanya #include <linux/types.h>
10222a4eeaSGeetha sowjanya #include <linux/device.h>
11222a4eeaSGeetha sowjanya #include <linux/module.h>
12222a4eeaSGeetha sowjanya #include <linux/pci.h>
13222a4eeaSGeetha sowjanya 
14222a4eeaSGeetha sowjanya #include "rvu.h"
15222a4eeaSGeetha sowjanya #include "rvu_reg.h"
16222a4eeaSGeetha sowjanya 
17b8fea84aSGeetha sowjanya #define M(_name, _id, _fn_name, _req_type, _rsp_type)			\
18b8fea84aSGeetha sowjanya static struct _req_type __maybe_unused					\
19b8fea84aSGeetha sowjanya *otx2_mbox_alloc_msg_ ## _fn_name(struct rvu *rvu, int devid)		\
20b8fea84aSGeetha sowjanya {									\
21b8fea84aSGeetha sowjanya 	struct _req_type *req;						\
22b8fea84aSGeetha sowjanya 									\
23b8fea84aSGeetha sowjanya 	req = (struct _req_type *)otx2_mbox_alloc_msg_rsp(		\
24b8fea84aSGeetha sowjanya 		&rvu->afpf_wq_info.mbox_up, devid, sizeof(struct _req_type), \
25b8fea84aSGeetha sowjanya 		sizeof(struct _rsp_type));				\
26b8fea84aSGeetha sowjanya 	if (!req)							\
27b8fea84aSGeetha sowjanya 		return NULL;						\
28b8fea84aSGeetha sowjanya 	req->hdr.sig = OTX2_MBOX_REQ_SIG;				\
29b8fea84aSGeetha sowjanya 	req->hdr.id = _id;						\
30b8fea84aSGeetha sowjanya 	return req;							\
31b8fea84aSGeetha sowjanya }
32b8fea84aSGeetha sowjanya 
33b8fea84aSGeetha sowjanya MBOX_UP_REP_MESSAGES
34b8fea84aSGeetha sowjanya #undef M
35b8fea84aSGeetha sowjanya 
36b8fea84aSGeetha sowjanya static int rvu_rep_up_notify(struct rvu *rvu, struct rep_event *event)
37b8fea84aSGeetha sowjanya {
389ed0343fSGeetha sowjanya 	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, event->pcifunc);
39b8fea84aSGeetha sowjanya 	struct rep_event *msg;
40b8fea84aSGeetha sowjanya 	int pf;
41b8fea84aSGeetha sowjanya 
42b8fea84aSGeetha sowjanya 	pf = rvu_get_pf(event->pcifunc);
43b8fea84aSGeetha sowjanya 
449ed0343fSGeetha sowjanya 	if (event->event & RVU_EVENT_MAC_ADDR_CHANGE)
459ed0343fSGeetha sowjanya 		ether_addr_copy(pfvf->mac_addr, event->evt_data.mac);
469ed0343fSGeetha sowjanya 
47b8fea84aSGeetha sowjanya 	mutex_lock(&rvu->mbox_lock);
48b8fea84aSGeetha sowjanya 	msg = otx2_mbox_alloc_msg_rep_event_up_notify(rvu, pf);
49b8fea84aSGeetha sowjanya 	if (!msg) {
50b8fea84aSGeetha sowjanya 		mutex_unlock(&rvu->mbox_lock);
51b8fea84aSGeetha sowjanya 		return -ENOMEM;
52b8fea84aSGeetha sowjanya 	}
53b8fea84aSGeetha sowjanya 
54b8fea84aSGeetha sowjanya 	msg->hdr.pcifunc = event->pcifunc;
55b8fea84aSGeetha sowjanya 	msg->event = event->event;
56b8fea84aSGeetha sowjanya 
57b8fea84aSGeetha sowjanya 	memcpy(&msg->evt_data, &event->evt_data, sizeof(struct rep_evt_data));
58b8fea84aSGeetha sowjanya 
59b8fea84aSGeetha sowjanya 	otx2_mbox_wait_for_zero(&rvu->afpf_wq_info.mbox_up, pf);
60b8fea84aSGeetha sowjanya 
61b8fea84aSGeetha sowjanya 	otx2_mbox_msg_send_up(&rvu->afpf_wq_info.mbox_up, pf);
62b8fea84aSGeetha sowjanya 
63b8fea84aSGeetha sowjanya 	mutex_unlock(&rvu->mbox_lock);
64b8fea84aSGeetha sowjanya 	return 0;
65b8fea84aSGeetha sowjanya }
66b8fea84aSGeetha sowjanya 
67b8fea84aSGeetha sowjanya static void rvu_rep_wq_handler(struct work_struct *work)
68b8fea84aSGeetha sowjanya {
69b8fea84aSGeetha sowjanya 	struct rvu *rvu = container_of(work, struct rvu, rep_evt_work);
70b8fea84aSGeetha sowjanya 	struct rep_evtq_ent *qentry;
71b8fea84aSGeetha sowjanya 	struct rep_event *event;
72b8fea84aSGeetha sowjanya 	unsigned long flags;
73b8fea84aSGeetha sowjanya 
74b8fea84aSGeetha sowjanya 	do {
75b8fea84aSGeetha sowjanya 		spin_lock_irqsave(&rvu->rep_evtq_lock, flags);
76b8fea84aSGeetha sowjanya 		qentry = list_first_entry_or_null(&rvu->rep_evtq_head,
77b8fea84aSGeetha sowjanya 						  struct rep_evtq_ent,
78b8fea84aSGeetha sowjanya 						  node);
79b8fea84aSGeetha sowjanya 		if (qentry)
80b8fea84aSGeetha sowjanya 			list_del(&qentry->node);
81b8fea84aSGeetha sowjanya 
82b8fea84aSGeetha sowjanya 		spin_unlock_irqrestore(&rvu->rep_evtq_lock, flags);
83b8fea84aSGeetha sowjanya 		if (!qentry)
84b8fea84aSGeetha sowjanya 			break; /* nothing more to process */
85b8fea84aSGeetha sowjanya 
86b8fea84aSGeetha sowjanya 		event = &qentry->event;
87b8fea84aSGeetha sowjanya 
88b8fea84aSGeetha sowjanya 		rvu_rep_up_notify(rvu, event);
89b8fea84aSGeetha sowjanya 		kfree(qentry);
90b8fea84aSGeetha sowjanya 	} while (1);
91b8fea84aSGeetha sowjanya }
92b8fea84aSGeetha sowjanya 
93b8fea84aSGeetha sowjanya int rvu_mbox_handler_rep_event_notify(struct rvu *rvu, struct rep_event *req,
94b8fea84aSGeetha sowjanya 				      struct msg_rsp *rsp)
95b8fea84aSGeetha sowjanya {
96b8fea84aSGeetha sowjanya 	struct rep_evtq_ent *qentry;
97b8fea84aSGeetha sowjanya 
98b8fea84aSGeetha sowjanya 	qentry = kmalloc(sizeof(*qentry), GFP_ATOMIC);
99b8fea84aSGeetha sowjanya 	if (!qentry)
100b8fea84aSGeetha sowjanya 		return -ENOMEM;
101b8fea84aSGeetha sowjanya 
102b8fea84aSGeetha sowjanya 	qentry->event = *req;
103b8fea84aSGeetha sowjanya 	spin_lock(&rvu->rep_evtq_lock);
104b8fea84aSGeetha sowjanya 	list_add_tail(&qentry->node, &rvu->rep_evtq_head);
105b8fea84aSGeetha sowjanya 	spin_unlock(&rvu->rep_evtq_lock);
106b8fea84aSGeetha sowjanya 	queue_work(rvu->rep_evt_wq, &rvu->rep_evt_work);
107b8fea84aSGeetha sowjanya 	return 0;
108b8fea84aSGeetha sowjanya }
109b8fea84aSGeetha sowjanya 
110b8fea84aSGeetha sowjanya int rvu_rep_notify_pfvf_state(struct rvu *rvu, u16 pcifunc, bool enable)
111b8fea84aSGeetha sowjanya {
112b8fea84aSGeetha sowjanya 	struct rep_event *req;
113b8fea84aSGeetha sowjanya 	int pf;
114b8fea84aSGeetha sowjanya 
115b8fea84aSGeetha sowjanya 	if (!is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc)))
116b8fea84aSGeetha sowjanya 		return 0;
117b8fea84aSGeetha sowjanya 
118b8fea84aSGeetha sowjanya 	pf = rvu_get_pf(rvu->rep_pcifunc);
119b8fea84aSGeetha sowjanya 
120b8fea84aSGeetha sowjanya 	mutex_lock(&rvu->mbox_lock);
121b8fea84aSGeetha sowjanya 	req = otx2_mbox_alloc_msg_rep_event_up_notify(rvu, pf);
122b8fea84aSGeetha sowjanya 	if (!req) {
123b8fea84aSGeetha sowjanya 		mutex_unlock(&rvu->mbox_lock);
124b8fea84aSGeetha sowjanya 		return -ENOMEM;
125b8fea84aSGeetha sowjanya 	}
126b8fea84aSGeetha sowjanya 
127b8fea84aSGeetha sowjanya 	req->hdr.pcifunc = rvu->rep_pcifunc;
128b8fea84aSGeetha sowjanya 	req->event |= RVU_EVENT_PFVF_STATE;
129b8fea84aSGeetha sowjanya 	req->pcifunc = pcifunc;
130b8fea84aSGeetha sowjanya 	req->evt_data.vf_state = enable;
131b8fea84aSGeetha sowjanya 
132b8fea84aSGeetha sowjanya 	otx2_mbox_wait_for_zero(&rvu->afpf_wq_info.mbox_up, pf);
133b8fea84aSGeetha sowjanya 	otx2_mbox_msg_send_up(&rvu->afpf_wq_info.mbox_up, pf);
134b8fea84aSGeetha sowjanya 
135b8fea84aSGeetha sowjanya 	mutex_unlock(&rvu->mbox_lock);
136b8fea84aSGeetha sowjanya 	return 0;
137b8fea84aSGeetha sowjanya }
138b8fea84aSGeetha sowjanya 
139940754a2SGeetha sowjanya #define RVU_LF_RX_STATS(reg) \
140940754a2SGeetha sowjanya 		rvu_read64(rvu, blkaddr, NIX_AF_LFX_RX_STATX(nixlf, reg))
141940754a2SGeetha sowjanya 
142940754a2SGeetha sowjanya #define RVU_LF_TX_STATS(reg) \
143940754a2SGeetha sowjanya 		rvu_read64(rvu, blkaddr, NIX_AF_LFX_TX_STATX(nixlf, reg))
144940754a2SGeetha sowjanya 
145940754a2SGeetha sowjanya int rvu_mbox_handler_nix_lf_stats(struct rvu *rvu,
146940754a2SGeetha sowjanya 				  struct nix_stats_req *req,
147940754a2SGeetha sowjanya 				  struct nix_stats_rsp *rsp)
148940754a2SGeetha sowjanya {
149940754a2SGeetha sowjanya 	u16 pcifunc = req->pcifunc;
150940754a2SGeetha sowjanya 	int nixlf, blkaddr, err;
151940754a2SGeetha sowjanya 	struct msg_req rst_req;
152940754a2SGeetha sowjanya 	struct msg_rsp rst_rsp;
153940754a2SGeetha sowjanya 
154940754a2SGeetha sowjanya 	err = nix_get_nixlf(rvu, pcifunc, &nixlf, &blkaddr);
155940754a2SGeetha sowjanya 	if (err)
156940754a2SGeetha sowjanya 		return 0;
157940754a2SGeetha sowjanya 
158940754a2SGeetha sowjanya 	if (req->reset) {
159940754a2SGeetha sowjanya 		rst_req.hdr.pcifunc = pcifunc;
160940754a2SGeetha sowjanya 		return rvu_mbox_handler_nix_stats_rst(rvu, &rst_req, &rst_rsp);
161940754a2SGeetha sowjanya 	}
162940754a2SGeetha sowjanya 	rsp->rx.octs = RVU_LF_RX_STATS(RX_OCTS);
163940754a2SGeetha sowjanya 	rsp->rx.ucast = RVU_LF_RX_STATS(RX_UCAST);
164940754a2SGeetha sowjanya 	rsp->rx.bcast = RVU_LF_RX_STATS(RX_BCAST);
165940754a2SGeetha sowjanya 	rsp->rx.mcast = RVU_LF_RX_STATS(RX_MCAST);
166940754a2SGeetha sowjanya 	rsp->rx.drop = RVU_LF_RX_STATS(RX_DROP);
167940754a2SGeetha sowjanya 	rsp->rx.err = RVU_LF_RX_STATS(RX_ERR);
168940754a2SGeetha sowjanya 	rsp->rx.drop_octs = RVU_LF_RX_STATS(RX_DROP_OCTS);
169940754a2SGeetha sowjanya 	rsp->rx.drop_mcast = RVU_LF_RX_STATS(RX_DRP_MCAST);
170940754a2SGeetha sowjanya 	rsp->rx.drop_bcast = RVU_LF_RX_STATS(RX_DRP_BCAST);
171940754a2SGeetha sowjanya 
172940754a2SGeetha sowjanya 	rsp->tx.octs = RVU_LF_TX_STATS(TX_OCTS);
173940754a2SGeetha sowjanya 	rsp->tx.ucast = RVU_LF_TX_STATS(TX_UCAST);
174940754a2SGeetha sowjanya 	rsp->tx.bcast = RVU_LF_TX_STATS(TX_BCAST);
175940754a2SGeetha sowjanya 	rsp->tx.mcast = RVU_LF_TX_STATS(TX_MCAST);
176940754a2SGeetha sowjanya 	rsp->tx.drop = RVU_LF_TX_STATS(TX_DROP);
177940754a2SGeetha sowjanya 
178940754a2SGeetha sowjanya 	rsp->pcifunc = req->pcifunc;
179940754a2SGeetha sowjanya 	return 0;
180940754a2SGeetha sowjanya }
181940754a2SGeetha sowjanya 
182683645a2SGeetha sowjanya static u16 rvu_rep_get_vlan_id(struct rvu *rvu, u16 pcifunc)
183683645a2SGeetha sowjanya {
184683645a2SGeetha sowjanya 	int id;
185683645a2SGeetha sowjanya 
186683645a2SGeetha sowjanya 	for (id = 0; id < rvu->rep_cnt; id++)
187683645a2SGeetha sowjanya 		if (rvu->rep2pfvf_map[id] == pcifunc)
188683645a2SGeetha sowjanya 			return id;
189683645a2SGeetha sowjanya 	return 0;
190683645a2SGeetha sowjanya }
191683645a2SGeetha sowjanya 
192683645a2SGeetha sowjanya static int rvu_rep_tx_vlan_cfg(struct rvu *rvu,  u16 pcifunc,
193683645a2SGeetha sowjanya 			       u16 vlan_tci, int *vidx)
194683645a2SGeetha sowjanya {
195683645a2SGeetha sowjanya 	struct nix_vtag_config_rsp rsp = {};
196683645a2SGeetha sowjanya 	struct nix_vtag_config req = {};
197683645a2SGeetha sowjanya 	u64 etype = ETH_P_8021Q;
198683645a2SGeetha sowjanya 	int err;
199683645a2SGeetha sowjanya 
200683645a2SGeetha sowjanya 	/* Insert vlan tag */
201683645a2SGeetha sowjanya 	req.hdr.pcifunc = pcifunc;
202683645a2SGeetha sowjanya 	req.vtag_size = VTAGSIZE_T4;
203683645a2SGeetha sowjanya 	req.cfg_type = 0; /* tx vlan cfg */
204683645a2SGeetha sowjanya 	req.tx.cfg_vtag0 = true;
205683645a2SGeetha sowjanya 	req.tx.vtag0 = FIELD_PREP(NIX_VLAN_ETYPE_MASK, etype) | vlan_tci;
206683645a2SGeetha sowjanya 
207683645a2SGeetha sowjanya 	err = rvu_mbox_handler_nix_vtag_cfg(rvu, &req, &rsp);
208683645a2SGeetha sowjanya 	if (err) {
209683645a2SGeetha sowjanya 		dev_err(rvu->dev, "Tx vlan config failed\n");
210683645a2SGeetha sowjanya 		return err;
211683645a2SGeetha sowjanya 	}
212683645a2SGeetha sowjanya 	*vidx = rsp.vtag0_idx;
213683645a2SGeetha sowjanya 	return 0;
214683645a2SGeetha sowjanya }
215683645a2SGeetha sowjanya 
216683645a2SGeetha sowjanya static int rvu_rep_rx_vlan_cfg(struct rvu *rvu, u16 pcifunc)
217683645a2SGeetha sowjanya {
218683645a2SGeetha sowjanya 	struct nix_vtag_config req = {};
219683645a2SGeetha sowjanya 	struct nix_vtag_config_rsp rsp;
220683645a2SGeetha sowjanya 
221683645a2SGeetha sowjanya 	/* config strip, capture and size */
222683645a2SGeetha sowjanya 	req.hdr.pcifunc = pcifunc;
223683645a2SGeetha sowjanya 	req.vtag_size = VTAGSIZE_T4;
224683645a2SGeetha sowjanya 	req.cfg_type = 1; /* rx vlan cfg */
225683645a2SGeetha sowjanya 	req.rx.vtag_type = NIX_AF_LFX_RX_VTAG_TYPE0;
226683645a2SGeetha sowjanya 	req.rx.strip_vtag = true;
227683645a2SGeetha sowjanya 	req.rx.capture_vtag = false;
228683645a2SGeetha sowjanya 
229683645a2SGeetha sowjanya 	return rvu_mbox_handler_nix_vtag_cfg(rvu, &req, &rsp);
230683645a2SGeetha sowjanya }
231683645a2SGeetha sowjanya 
232683645a2SGeetha sowjanya static int rvu_rep_install_rx_rule(struct rvu *rvu, u16 pcifunc,
233683645a2SGeetha sowjanya 				   u16 entry, bool rte)
234683645a2SGeetha sowjanya {
235683645a2SGeetha sowjanya 	struct npc_install_flow_req req = {};
236683645a2SGeetha sowjanya 	struct npc_install_flow_rsp rsp = {};
237683645a2SGeetha sowjanya 	struct rvu_pfvf *pfvf;
238683645a2SGeetha sowjanya 	u16 vlan_tci, rep_id;
239683645a2SGeetha sowjanya 
240683645a2SGeetha sowjanya 	pfvf = rvu_get_pfvf(rvu, pcifunc);
241683645a2SGeetha sowjanya 
242683645a2SGeetha sowjanya 	/* To steer the traffic from Representee to Representor */
243683645a2SGeetha sowjanya 	rep_id = rvu_rep_get_vlan_id(rvu, pcifunc);
244683645a2SGeetha sowjanya 	if (rte) {
245683645a2SGeetha sowjanya 		vlan_tci = rep_id | BIT_ULL(8);
246683645a2SGeetha sowjanya 		req.vf = rvu->rep_pcifunc;
247683645a2SGeetha sowjanya 		req.op = NIX_RX_ACTIONOP_UCAST;
248683645a2SGeetha sowjanya 		req.index = rep_id;
249683645a2SGeetha sowjanya 	} else {
250683645a2SGeetha sowjanya 		vlan_tci = rep_id;
251683645a2SGeetha sowjanya 		req.vf = pcifunc;
252683645a2SGeetha sowjanya 		req.op = NIX_RX_ACTION_DEFAULT;
253683645a2SGeetha sowjanya 	}
254683645a2SGeetha sowjanya 
255683645a2SGeetha sowjanya 	rvu_rep_rx_vlan_cfg(rvu, req.vf);
256683645a2SGeetha sowjanya 	req.entry = entry;
257683645a2SGeetha sowjanya 	req.hdr.pcifunc = 0; /* AF is requester */
258683645a2SGeetha sowjanya 	req.features = BIT_ULL(NPC_OUTER_VID) | BIT_ULL(NPC_VLAN_ETYPE_CTAG);
259683645a2SGeetha sowjanya 	req.vtag0_valid = true;
260683645a2SGeetha sowjanya 	req.vtag0_type = NIX_AF_LFX_RX_VTAG_TYPE0;
261683645a2SGeetha sowjanya 	req.packet.vlan_etype = cpu_to_be16(ETH_P_8021Q);
262683645a2SGeetha sowjanya 	req.mask.vlan_etype = cpu_to_be16(ETH_P_8021Q);
263683645a2SGeetha sowjanya 	req.packet.vlan_tci = cpu_to_be16(vlan_tci);
264683645a2SGeetha sowjanya 	req.mask.vlan_tci = cpu_to_be16(0xffff);
265683645a2SGeetha sowjanya 
266683645a2SGeetha sowjanya 	req.channel = RVU_SWITCH_LBK_CHAN;
267683645a2SGeetha sowjanya 	req.chan_mask = 0xffff;
268683645a2SGeetha sowjanya 	req.intf = pfvf->nix_rx_intf;
269683645a2SGeetha sowjanya 
270683645a2SGeetha sowjanya 	return rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
271683645a2SGeetha sowjanya }
272683645a2SGeetha sowjanya 
273683645a2SGeetha sowjanya static int rvu_rep_install_tx_rule(struct rvu *rvu, u16 pcifunc, u16 entry,
274683645a2SGeetha sowjanya 				   bool rte)
275683645a2SGeetha sowjanya {
276683645a2SGeetha sowjanya 	struct npc_install_flow_req req = {};
277683645a2SGeetha sowjanya 	struct npc_install_flow_rsp rsp = {};
278683645a2SGeetha sowjanya 	struct rvu_pfvf *pfvf;
279683645a2SGeetha sowjanya 	int vidx, err;
280683645a2SGeetha sowjanya 	u16 vlan_tci;
281683645a2SGeetha sowjanya 	u8 lbkid;
282683645a2SGeetha sowjanya 
283683645a2SGeetha sowjanya 	pfvf = rvu_get_pfvf(rvu, pcifunc);
284683645a2SGeetha sowjanya 	vlan_tci = rvu_rep_get_vlan_id(rvu, pcifunc);
285683645a2SGeetha sowjanya 	if (rte)
286683645a2SGeetha sowjanya 		vlan_tci |= BIT_ULL(8);
287683645a2SGeetha sowjanya 
288683645a2SGeetha sowjanya 	err = rvu_rep_tx_vlan_cfg(rvu, pcifunc, vlan_tci, &vidx);
289683645a2SGeetha sowjanya 	if (err)
290683645a2SGeetha sowjanya 		return err;
291683645a2SGeetha sowjanya 
292683645a2SGeetha sowjanya 	lbkid = pfvf->nix_blkaddr == BLKADDR_NIX0 ? 0 : 1;
293683645a2SGeetha sowjanya 	req.hdr.pcifunc = 0; /* AF is requester */
294683645a2SGeetha sowjanya 	if (rte) {
295683645a2SGeetha sowjanya 		req.vf = pcifunc;
296683645a2SGeetha sowjanya 	} else {
297683645a2SGeetha sowjanya 		req.vf = rvu->rep_pcifunc;
298683645a2SGeetha sowjanya 		req.packet.sq_id = vlan_tci;
299683645a2SGeetha sowjanya 		req.mask.sq_id = 0xffff;
300683645a2SGeetha sowjanya 	}
301683645a2SGeetha sowjanya 
302683645a2SGeetha sowjanya 	req.entry = entry;
303683645a2SGeetha sowjanya 	req.intf = pfvf->nix_tx_intf;
304683645a2SGeetha sowjanya 	req.op = NIX_TX_ACTIONOP_UCAST_CHAN;
305683645a2SGeetha sowjanya 	req.index = (lbkid << 8) | RVU_SWITCH_LBK_CHAN;
306683645a2SGeetha sowjanya 	req.set_cntr = 1;
307683645a2SGeetha sowjanya 	req.vtag0_def = vidx;
308683645a2SGeetha sowjanya 	req.vtag0_op = 1;
309683645a2SGeetha sowjanya 	return rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
310683645a2SGeetha sowjanya }
311683645a2SGeetha sowjanya 
312683645a2SGeetha sowjanya int rvu_rep_install_mcam_rules(struct rvu *rvu)
313683645a2SGeetha sowjanya {
314683645a2SGeetha sowjanya 	struct rvu_switch *rswitch = &rvu->rswitch;
315683645a2SGeetha sowjanya 	u16 start = rswitch->start_entry;
316683645a2SGeetha sowjanya 	struct rvu_hwinfo *hw = rvu->hw;
317683645a2SGeetha sowjanya 	u16 pcifunc, entry = 0;
318683645a2SGeetha sowjanya 	int pf, vf, numvfs;
319683645a2SGeetha sowjanya 	int err, nixlf, i;
320683645a2SGeetha sowjanya 	u8 rep;
321683645a2SGeetha sowjanya 
322683645a2SGeetha sowjanya 	for (pf = 1; pf < hw->total_pfs; pf++) {
323683645a2SGeetha sowjanya 		if (!is_pf_cgxmapped(rvu, pf))
324683645a2SGeetha sowjanya 			continue;
325683645a2SGeetha sowjanya 
326683645a2SGeetha sowjanya 		pcifunc = pf << RVU_PFVF_PF_SHIFT;
327683645a2SGeetha sowjanya 		rvu_get_nix_blkaddr(rvu, pcifunc);
328683645a2SGeetha sowjanya 		rep = true;
329683645a2SGeetha sowjanya 		for (i = 0; i < 2; i++) {
330683645a2SGeetha sowjanya 			err = rvu_rep_install_rx_rule(rvu, pcifunc,
331683645a2SGeetha sowjanya 						      start + entry, rep);
332683645a2SGeetha sowjanya 			if (err)
333683645a2SGeetha sowjanya 				return err;
334683645a2SGeetha sowjanya 			rswitch->entry2pcifunc[entry++] = pcifunc;
335683645a2SGeetha sowjanya 
336683645a2SGeetha sowjanya 			err = rvu_rep_install_tx_rule(rvu, pcifunc,
337683645a2SGeetha sowjanya 						      start + entry, rep);
338683645a2SGeetha sowjanya 			if (err)
339683645a2SGeetha sowjanya 				return err;
340683645a2SGeetha sowjanya 			rswitch->entry2pcifunc[entry++] = pcifunc;
341683645a2SGeetha sowjanya 			rep = false;
342683645a2SGeetha sowjanya 		}
343683645a2SGeetha sowjanya 
344683645a2SGeetha sowjanya 		rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL);
345683645a2SGeetha sowjanya 		for (vf = 0; vf < numvfs; vf++) {
346683645a2SGeetha sowjanya 			pcifunc = pf << RVU_PFVF_PF_SHIFT |
347683645a2SGeetha sowjanya 				  ((vf + 1) & RVU_PFVF_FUNC_MASK);
348683645a2SGeetha sowjanya 			rvu_get_nix_blkaddr(rvu, pcifunc);
349683645a2SGeetha sowjanya 
350683645a2SGeetha sowjanya 			/* Skip installimg rules if nixlf is not attached */
351683645a2SGeetha sowjanya 			err = nix_get_nixlf(rvu, pcifunc, &nixlf, NULL);
352683645a2SGeetha sowjanya 			if (err)
353683645a2SGeetha sowjanya 				continue;
354683645a2SGeetha sowjanya 			rep = true;
355683645a2SGeetha sowjanya 			for (i = 0; i < 2; i++) {
356683645a2SGeetha sowjanya 				err = rvu_rep_install_rx_rule(rvu, pcifunc,
357683645a2SGeetha sowjanya 							      start + entry,
358683645a2SGeetha sowjanya 							      rep);
359683645a2SGeetha sowjanya 				if (err)
360683645a2SGeetha sowjanya 					return err;
361683645a2SGeetha sowjanya 				rswitch->entry2pcifunc[entry++] = pcifunc;
362683645a2SGeetha sowjanya 
363683645a2SGeetha sowjanya 				err = rvu_rep_install_tx_rule(rvu, pcifunc,
364683645a2SGeetha sowjanya 							      start + entry,
365683645a2SGeetha sowjanya 							      rep);
366683645a2SGeetha sowjanya 				if (err)
367683645a2SGeetha sowjanya 					return err;
368683645a2SGeetha sowjanya 				rswitch->entry2pcifunc[entry++] = pcifunc;
369683645a2SGeetha sowjanya 				rep = false;
370683645a2SGeetha sowjanya 			}
371683645a2SGeetha sowjanya 		}
372683645a2SGeetha sowjanya 	}
373b8fea84aSGeetha sowjanya 
374b8fea84aSGeetha sowjanya 	/* Initialize the wq for handling REP events */
375b8fea84aSGeetha sowjanya 	spin_lock_init(&rvu->rep_evtq_lock);
376b8fea84aSGeetha sowjanya 	INIT_LIST_HEAD(&rvu->rep_evtq_head);
377b8fea84aSGeetha sowjanya 	INIT_WORK(&rvu->rep_evt_work, rvu_rep_wq_handler);
378b8fea84aSGeetha sowjanya 	rvu->rep_evt_wq = alloc_workqueue("rep_evt_wq", 0, 0);
379b8fea84aSGeetha sowjanya 	if (!rvu->rep_evt_wq) {
380b8fea84aSGeetha sowjanya 		dev_err(rvu->dev, "REP workqueue allocation failed\n");
381b8fea84aSGeetha sowjanya 		return -ENOMEM;
382b8fea84aSGeetha sowjanya 	}
383683645a2SGeetha sowjanya 	return 0;
384683645a2SGeetha sowjanya }
385683645a2SGeetha sowjanya 
386683645a2SGeetha sowjanya void rvu_rep_update_rules(struct rvu *rvu, u16 pcifunc, bool ena)
387683645a2SGeetha sowjanya {
388683645a2SGeetha sowjanya 	struct rvu_switch *rswitch = &rvu->rswitch;
389683645a2SGeetha sowjanya 	struct npc_mcam *mcam = &rvu->hw->mcam;
390683645a2SGeetha sowjanya 	u32 max = rswitch->used_entries;
391683645a2SGeetha sowjanya 	int blkaddr;
392683645a2SGeetha sowjanya 	u16 entry;
393683645a2SGeetha sowjanya 
394683645a2SGeetha sowjanya 	if (!rswitch->used_entries)
395683645a2SGeetha sowjanya 		return;
396683645a2SGeetha sowjanya 
397683645a2SGeetha sowjanya 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
398683645a2SGeetha sowjanya 
399683645a2SGeetha sowjanya 	if (blkaddr < 0)
400683645a2SGeetha sowjanya 		return;
401683645a2SGeetha sowjanya 
402683645a2SGeetha sowjanya 	rvu_switch_enable_lbk_link(rvu, pcifunc, ena);
403683645a2SGeetha sowjanya 	mutex_lock(&mcam->lock);
404683645a2SGeetha sowjanya 	for (entry = 0; entry < max; entry++) {
405683645a2SGeetha sowjanya 		if (rswitch->entry2pcifunc[entry] == pcifunc)
406683645a2SGeetha sowjanya 			npc_enable_mcam_entry(rvu, mcam, blkaddr, entry, ena);
407683645a2SGeetha sowjanya 	}
408683645a2SGeetha sowjanya 	mutex_unlock(&mcam->lock);
409683645a2SGeetha sowjanya }
410683645a2SGeetha sowjanya 
411683645a2SGeetha sowjanya int rvu_rep_pf_init(struct rvu *rvu)
412683645a2SGeetha sowjanya {
413683645a2SGeetha sowjanya 	u16 pcifunc = rvu->rep_pcifunc;
414683645a2SGeetha sowjanya 	struct rvu_pfvf *pfvf;
415683645a2SGeetha sowjanya 
416683645a2SGeetha sowjanya 	pfvf = rvu_get_pfvf(rvu, pcifunc);
417683645a2SGeetha sowjanya 	set_bit(NIXLF_INITIALIZED, &pfvf->flags);
418683645a2SGeetha sowjanya 	rvu_switch_enable_lbk_link(rvu, pcifunc, true);
419683645a2SGeetha sowjanya 	rvu_rep_rx_vlan_cfg(rvu, pcifunc);
420683645a2SGeetha sowjanya 	return 0;
421683645a2SGeetha sowjanya }
422683645a2SGeetha sowjanya 
423683645a2SGeetha sowjanya int rvu_mbox_handler_esw_cfg(struct rvu *rvu, struct esw_cfg_req *req,
424683645a2SGeetha sowjanya 			     struct msg_rsp *rsp)
425683645a2SGeetha sowjanya {
426683645a2SGeetha sowjanya 	if (req->hdr.pcifunc != rvu->rep_pcifunc)
427683645a2SGeetha sowjanya 		return 0;
428683645a2SGeetha sowjanya 
429683645a2SGeetha sowjanya 	rvu->rep_mode = req->ena;
430*6c40ca95SGeetha sowjanya 
431*6c40ca95SGeetha sowjanya 	if (!rvu->rep_mode)
432*6c40ca95SGeetha sowjanya 		rvu_npc_free_mcam_entries(rvu, req->hdr.pcifunc, -1);
433*6c40ca95SGeetha sowjanya 
434683645a2SGeetha sowjanya 	return 0;
435683645a2SGeetha sowjanya }
436683645a2SGeetha sowjanya 
437222a4eeaSGeetha sowjanya int rvu_mbox_handler_get_rep_cnt(struct rvu *rvu, struct msg_req *req,
438222a4eeaSGeetha sowjanya 				 struct get_rep_cnt_rsp *rsp)
439222a4eeaSGeetha sowjanya {
440222a4eeaSGeetha sowjanya 	int pf, vf, numvfs, hwvf, rep = 0;
441222a4eeaSGeetha sowjanya 	u16 pcifunc;
442222a4eeaSGeetha sowjanya 
443222a4eeaSGeetha sowjanya 	rvu->rep_pcifunc = req->hdr.pcifunc;
444222a4eeaSGeetha sowjanya 	rsp->rep_cnt = rvu->cgx_mapped_pfs + rvu->cgx_mapped_vfs;
445222a4eeaSGeetha sowjanya 	rvu->rep_cnt = rsp->rep_cnt;
446222a4eeaSGeetha sowjanya 
447222a4eeaSGeetha sowjanya 	rvu->rep2pfvf_map = devm_kzalloc(rvu->dev, rvu->rep_cnt *
448222a4eeaSGeetha sowjanya 					 sizeof(u16), GFP_KERNEL);
449222a4eeaSGeetha sowjanya 	if (!rvu->rep2pfvf_map)
450222a4eeaSGeetha sowjanya 		return -ENOMEM;
451222a4eeaSGeetha sowjanya 
452222a4eeaSGeetha sowjanya 	for (pf = 0; pf < rvu->hw->total_pfs; pf++) {
453222a4eeaSGeetha sowjanya 		if (!is_pf_cgxmapped(rvu, pf))
454222a4eeaSGeetha sowjanya 			continue;
455222a4eeaSGeetha sowjanya 		pcifunc = pf << RVU_PFVF_PF_SHIFT;
456222a4eeaSGeetha sowjanya 		rvu->rep2pfvf_map[rep] = pcifunc;
457222a4eeaSGeetha sowjanya 		rsp->rep_pf_map[rep] = pcifunc;
458222a4eeaSGeetha sowjanya 		rep++;
459222a4eeaSGeetha sowjanya 		rvu_get_pf_numvfs(rvu, pf, &numvfs, &hwvf);
460222a4eeaSGeetha sowjanya 		for (vf = 0; vf < numvfs; vf++) {
461222a4eeaSGeetha sowjanya 			rvu->rep2pfvf_map[rep] = pcifunc |
462222a4eeaSGeetha sowjanya 				((vf + 1) & RVU_PFVF_FUNC_MASK);
463222a4eeaSGeetha sowjanya 			rsp->rep_pf_map[rep] = rvu->rep2pfvf_map[rep];
464222a4eeaSGeetha sowjanya 			rep++;
465222a4eeaSGeetha sowjanya 		}
466222a4eeaSGeetha sowjanya 	}
467222a4eeaSGeetha sowjanya 	return 0;
468222a4eeaSGeetha sowjanya }
469