1cde29af9SShinas Rasheed // SPDX-License-Identifier: GPL-2.0
2cde29af9SShinas Rasheed /* Marvell Octeon EP (EndPoint) Ethernet Driver
3cde29af9SShinas Rasheed  *
4cde29af9SShinas Rasheed  * Copyright (C) 2020 Marvell.
5cde29af9SShinas Rasheed  *
6cde29af9SShinas Rasheed  */
7cde29af9SShinas Rasheed 
8cde29af9SShinas Rasheed #include <linux/types.h>
9cde29af9SShinas Rasheed #include <linux/errno.h>
10cde29af9SShinas Rasheed #include <linux/string.h>
11cde29af9SShinas Rasheed #include <linux/mutex.h>
12cde29af9SShinas Rasheed #include <linux/jiffies.h>
13cde29af9SShinas Rasheed #include <linux/sched.h>
14cde29af9SShinas Rasheed #include <linux/sched/signal.h>
15cde29af9SShinas Rasheed #include <linux/io.h>
16cde29af9SShinas Rasheed #include <linux/pci.h>
17cde29af9SShinas Rasheed #include <linux/etherdevice.h>
18*0069455bSKent Overstreet #include <linux/vmalloc.h>
19cde29af9SShinas Rasheed 
20cde29af9SShinas Rasheed #include "octep_config.h"
21cde29af9SShinas Rasheed #include "octep_main.h"
22cde29af9SShinas Rasheed #include "octep_pfvf_mbox.h"
23cde29af9SShinas Rasheed #include "octep_ctrl_net.h"
24cde29af9SShinas Rasheed 
254ebb86a9SShinas Rasheed /* When a new command is implemented, the below table should be updated
264ebb86a9SShinas Rasheed  * with new command and it's version info.
274ebb86a9SShinas Rasheed  */
284ebb86a9SShinas Rasheed static u32 pfvf_cmd_versions[OCTEP_PFVF_MBOX_CMD_MAX] = {
294ebb86a9SShinas Rasheed 	[0 ... OCTEP_PFVF_MBOX_CMD_DEV_REMOVE] = OCTEP_PFVF_MBOX_VERSION_V1,
304ebb86a9SShinas Rasheed 	[OCTEP_PFVF_MBOX_CMD_GET_FW_INFO ... OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS] =
314ebb86a9SShinas Rasheed 		OCTEP_PFVF_MBOX_VERSION_V2
324ebb86a9SShinas Rasheed };
334ebb86a9SShinas Rasheed 
octep_pfvf_validate_version(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)34cde29af9SShinas Rasheed static void octep_pfvf_validate_version(struct octep_device *oct,  u32 vf_id,
35cde29af9SShinas Rasheed 					union octep_pfvf_mbox_word cmd,
36cde29af9SShinas Rasheed 					union octep_pfvf_mbox_word *rsp)
37cde29af9SShinas Rasheed {
38cde29af9SShinas Rasheed 	u32 vf_version = (u32)cmd.s_version.version;
39cde29af9SShinas Rasheed 
40c130e589SShinas Rasheed 	dev_dbg(&oct->pdev->dev, "VF id:%d VF version:%d PF version:%d\n",
41c130e589SShinas Rasheed 		vf_id, vf_version, OCTEP_PFVF_MBOX_VERSION_CURRENT);
42c130e589SShinas Rasheed 	if (vf_version < OCTEP_PFVF_MBOX_VERSION_CURRENT)
43c130e589SShinas Rasheed 		rsp->s_version.version = vf_version;
44cde29af9SShinas Rasheed 	else
45c130e589SShinas Rasheed 		rsp->s_version.version = OCTEP_PFVF_MBOX_VERSION_CURRENT;
46c130e589SShinas Rasheed 
47c130e589SShinas Rasheed 	oct->vf_info[vf_id].mbox_version = rsp->s_version.version;
48c130e589SShinas Rasheed 	dev_dbg(&oct->pdev->dev, "VF id:%d negotiated VF version:%d\n",
49c130e589SShinas Rasheed 		vf_id, oct->vf_info[vf_id].mbox_version);
50c130e589SShinas Rasheed 
51c130e589SShinas Rasheed 	rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
52cde29af9SShinas Rasheed }
53cde29af9SShinas Rasheed 
octep_pfvf_get_link_status(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)54cde29af9SShinas Rasheed static void octep_pfvf_get_link_status(struct octep_device *oct, u32 vf_id,
55cde29af9SShinas Rasheed 				       union octep_pfvf_mbox_word cmd,
56cde29af9SShinas Rasheed 				       union octep_pfvf_mbox_word *rsp)
57cde29af9SShinas Rasheed {
58cde29af9SShinas Rasheed 	int status;
59cde29af9SShinas Rasheed 
60cde29af9SShinas Rasheed 	status = octep_ctrl_net_get_link_status(oct, vf_id);
61cde29af9SShinas Rasheed 	if (status < 0) {
62cde29af9SShinas Rasheed 		rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
63cde29af9SShinas Rasheed 		dev_err(&oct->pdev->dev, "Get VF link status failed via host control Mbox\n");
64cde29af9SShinas Rasheed 		return;
65cde29af9SShinas Rasheed 	}
66cde29af9SShinas Rasheed 	rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
67cde29af9SShinas Rasheed 	rsp->s_link_status.status = status;
68cde29af9SShinas Rasheed }
69cde29af9SShinas Rasheed 
octep_pfvf_set_link_status(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)70cde29af9SShinas Rasheed static void octep_pfvf_set_link_status(struct octep_device *oct, u32 vf_id,
71cde29af9SShinas Rasheed 				       union octep_pfvf_mbox_word cmd,
72cde29af9SShinas Rasheed 				       union octep_pfvf_mbox_word *rsp)
73cde29af9SShinas Rasheed {
74cde29af9SShinas Rasheed 	int err;
75cde29af9SShinas Rasheed 
76cde29af9SShinas Rasheed 	err = octep_ctrl_net_set_link_status(oct, vf_id, cmd.s_link_status.status, true);
77cde29af9SShinas Rasheed 	if (err) {
78cde29af9SShinas Rasheed 		rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
79cde29af9SShinas Rasheed 		dev_err(&oct->pdev->dev, "Set VF link status failed via host control Mbox\n");
80cde29af9SShinas Rasheed 		return;
81cde29af9SShinas Rasheed 	}
82cde29af9SShinas Rasheed 	rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
83cde29af9SShinas Rasheed }
84cde29af9SShinas Rasheed 
octep_pfvf_set_rx_state(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)85cde29af9SShinas Rasheed static void octep_pfvf_set_rx_state(struct octep_device *oct, u32 vf_id,
86cde29af9SShinas Rasheed 				    union octep_pfvf_mbox_word cmd,
87cde29af9SShinas Rasheed 				    union octep_pfvf_mbox_word *rsp)
88cde29af9SShinas Rasheed {
89cde29af9SShinas Rasheed 	int err;
90cde29af9SShinas Rasheed 
91cde29af9SShinas Rasheed 	err = octep_ctrl_net_set_rx_state(oct, vf_id, cmd.s_link_state.state, true);
92cde29af9SShinas Rasheed 	if (err) {
93cde29af9SShinas Rasheed 		rsp->s_link_state.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
94cde29af9SShinas Rasheed 		dev_err(&oct->pdev->dev, "Set VF Rx link state failed via host control Mbox\n");
95cde29af9SShinas Rasheed 		return;
96cde29af9SShinas Rasheed 	}
97cde29af9SShinas Rasheed 	rsp->s_link_state.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
98cde29af9SShinas Rasheed }
99cde29af9SShinas Rasheed 
octep_send_notification(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd)1004ebb86a9SShinas Rasheed static int octep_send_notification(struct octep_device *oct, u32 vf_id,
1014ebb86a9SShinas Rasheed 				   union octep_pfvf_mbox_word cmd)
1024ebb86a9SShinas Rasheed {
1034ebb86a9SShinas Rasheed 	u32 max_rings_per_vf, vf_mbox_queue;
1044ebb86a9SShinas Rasheed 	struct octep_mbox *mbox;
1054ebb86a9SShinas Rasheed 
1064ebb86a9SShinas Rasheed 	/* check if VF PF Mailbox is compatible for this notification */
1074ebb86a9SShinas Rasheed 	if (pfvf_cmd_versions[cmd.s.opcode] > oct->vf_info[vf_id].mbox_version) {
1084ebb86a9SShinas Rasheed 		dev_dbg(&oct->pdev->dev, "VF Mbox doesn't support Notification:%d on VF ver:%d\n",
1094ebb86a9SShinas Rasheed 			cmd.s.opcode, oct->vf_info[vf_id].mbox_version);
1104ebb86a9SShinas Rasheed 		return -EOPNOTSUPP;
1114ebb86a9SShinas Rasheed 	}
1124ebb86a9SShinas Rasheed 
1134ebb86a9SShinas Rasheed 	max_rings_per_vf = CFG_GET_MAX_RPVF(oct->conf);
1144ebb86a9SShinas Rasheed 	vf_mbox_queue = vf_id * max_rings_per_vf;
1154ebb86a9SShinas Rasheed 	if (!oct->mbox[vf_mbox_queue]) {
1164ebb86a9SShinas Rasheed 		dev_err(&oct->pdev->dev, "Notif obtained for bad mbox vf %d\n", vf_id);
1174ebb86a9SShinas Rasheed 		return -EINVAL;
1184ebb86a9SShinas Rasheed 	}
1194ebb86a9SShinas Rasheed 	mbox = oct->mbox[vf_mbox_queue];
1204ebb86a9SShinas Rasheed 
1214ebb86a9SShinas Rasheed 	mutex_lock(&mbox->lock);
1224ebb86a9SShinas Rasheed 	writeq(cmd.u64, mbox->pf_vf_data_reg);
1234ebb86a9SShinas Rasheed 	mutex_unlock(&mbox->lock);
1244ebb86a9SShinas Rasheed 
1254ebb86a9SShinas Rasheed 	return 0;
1264ebb86a9SShinas Rasheed }
1274ebb86a9SShinas Rasheed 
octep_pfvf_set_mtu(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)128cde29af9SShinas Rasheed static void octep_pfvf_set_mtu(struct octep_device *oct, u32 vf_id,
129cde29af9SShinas Rasheed 			       union octep_pfvf_mbox_word cmd,
130cde29af9SShinas Rasheed 			       union octep_pfvf_mbox_word *rsp)
131cde29af9SShinas Rasheed {
132cde29af9SShinas Rasheed 	int err;
133cde29af9SShinas Rasheed 
134cde29af9SShinas Rasheed 	err = octep_ctrl_net_set_mtu(oct, vf_id, cmd.s_set_mtu.mtu, true);
135cde29af9SShinas Rasheed 	if (err) {
136cde29af9SShinas Rasheed 		rsp->s_set_mtu.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
137cde29af9SShinas Rasheed 		dev_err(&oct->pdev->dev, "Set VF MTU failed via host control Mbox\n");
138cde29af9SShinas Rasheed 		return;
139cde29af9SShinas Rasheed 	}
140cde29af9SShinas Rasheed 	rsp->s_set_mtu.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
141cde29af9SShinas Rasheed }
142cde29af9SShinas Rasheed 
octep_pfvf_get_mtu(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)143cde29af9SShinas Rasheed static void octep_pfvf_get_mtu(struct octep_device *oct, u32 vf_id,
144cde29af9SShinas Rasheed 			       union octep_pfvf_mbox_word cmd,
145cde29af9SShinas Rasheed 			       union octep_pfvf_mbox_word *rsp)
146cde29af9SShinas Rasheed {
147cde29af9SShinas Rasheed 	int max_rx_pktlen = oct->netdev->max_mtu + (ETH_HLEN + ETH_FCS_LEN);
148cde29af9SShinas Rasheed 
149cde29af9SShinas Rasheed 	rsp->s_set_mtu.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
150cde29af9SShinas Rasheed 	rsp->s_get_mtu.mtu = max_rx_pktlen;
151cde29af9SShinas Rasheed }
152cde29af9SShinas Rasheed 
octep_pfvf_set_mac_addr(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)153cde29af9SShinas Rasheed static void octep_pfvf_set_mac_addr(struct octep_device *oct,  u32 vf_id,
154cde29af9SShinas Rasheed 				    union octep_pfvf_mbox_word cmd,
155cde29af9SShinas Rasheed 				    union octep_pfvf_mbox_word *rsp)
156cde29af9SShinas Rasheed {
157cde29af9SShinas Rasheed 	int err;
158cde29af9SShinas Rasheed 
159cde29af9SShinas Rasheed 	err = octep_ctrl_net_set_mac_addr(oct, vf_id, cmd.s_set_mac.mac_addr, true);
160cde29af9SShinas Rasheed 	if (err) {
161cde29af9SShinas Rasheed 		rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
162cde29af9SShinas Rasheed 		dev_err(&oct->pdev->dev, "Set VF MAC address failed via host control Mbox\n");
163cde29af9SShinas Rasheed 		return;
164cde29af9SShinas Rasheed 	}
165cde29af9SShinas Rasheed 	rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
166cde29af9SShinas Rasheed }
167cde29af9SShinas Rasheed 
octep_pfvf_get_mac_addr(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)168cde29af9SShinas Rasheed static void octep_pfvf_get_mac_addr(struct octep_device *oct,  u32 vf_id,
169cde29af9SShinas Rasheed 				    union octep_pfvf_mbox_word cmd,
170cde29af9SShinas Rasheed 				    union octep_pfvf_mbox_word *rsp)
171cde29af9SShinas Rasheed {
172cde29af9SShinas Rasheed 	int err;
173cde29af9SShinas Rasheed 
174cde29af9SShinas Rasheed 	err = octep_ctrl_net_get_mac_addr(oct, vf_id, rsp->s_set_mac.mac_addr);
175cde29af9SShinas Rasheed 	if (err) {
176cde29af9SShinas Rasheed 		rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
177cde29af9SShinas Rasheed 		dev_err(&oct->pdev->dev, "Get VF MAC address failed via host control Mbox\n");
178cde29af9SShinas Rasheed 		return;
179cde29af9SShinas Rasheed 	}
180cde29af9SShinas Rasheed 	rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
181cde29af9SShinas Rasheed }
182cde29af9SShinas Rasheed 
octep_pfvf_dev_remove(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)183cde29af9SShinas Rasheed static void octep_pfvf_dev_remove(struct octep_device *oct,  u32 vf_id,
184cde29af9SShinas Rasheed 				  union octep_pfvf_mbox_word cmd,
185cde29af9SShinas Rasheed 				  union octep_pfvf_mbox_word *rsp)
186cde29af9SShinas Rasheed {
187cde29af9SShinas Rasheed 	int err;
188cde29af9SShinas Rasheed 
189cde29af9SShinas Rasheed 	err = octep_ctrl_net_dev_remove(oct, vf_id);
190cde29af9SShinas Rasheed 	if (err) {
191cde29af9SShinas Rasheed 		rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
192cde29af9SShinas Rasheed 		dev_err(&oct->pdev->dev, "Failed to acknowledge fw of vf %d removal\n",
193cde29af9SShinas Rasheed 			vf_id);
194cde29af9SShinas Rasheed 		return;
195cde29af9SShinas Rasheed 	}
196cde29af9SShinas Rasheed 	rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
197cde29af9SShinas Rasheed }
198cde29af9SShinas Rasheed 
octep_pfvf_get_fw_info(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)199e28db8cbSShinas Rasheed static void octep_pfvf_get_fw_info(struct octep_device *oct,  u32 vf_id,
200e28db8cbSShinas Rasheed 				   union octep_pfvf_mbox_word cmd,
201e28db8cbSShinas Rasheed 				   union octep_pfvf_mbox_word *rsp)
202e28db8cbSShinas Rasheed {
203e28db8cbSShinas Rasheed 	struct octep_fw_info fw_info;
204e28db8cbSShinas Rasheed 	int err;
205e28db8cbSShinas Rasheed 
206e28db8cbSShinas Rasheed 	err = octep_ctrl_net_get_info(oct, vf_id, &fw_info);
207e28db8cbSShinas Rasheed 	if (err) {
208e28db8cbSShinas Rasheed 		rsp->s_fw_info.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
209e28db8cbSShinas Rasheed 		dev_err(&oct->pdev->dev, "Get VF info failed via host control Mbox\n");
210e28db8cbSShinas Rasheed 		return;
211e28db8cbSShinas Rasheed 	}
212e28db8cbSShinas Rasheed 
213e28db8cbSShinas Rasheed 	rsp->s_fw_info.pkind = fw_info.pkind;
214e28db8cbSShinas Rasheed 	rsp->s_fw_info.fsz = fw_info.fsz;
215e28db8cbSShinas Rasheed 	rsp->s_fw_info.rx_ol_flags = fw_info.rx_ol_flags;
216e28db8cbSShinas Rasheed 	rsp->s_fw_info.tx_ol_flags = fw_info.tx_ol_flags;
217e28db8cbSShinas Rasheed 
218e28db8cbSShinas Rasheed 	rsp->s_fw_info.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
219e28db8cbSShinas Rasheed }
220e28db8cbSShinas Rasheed 
octep_pfvf_set_offloads(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)221e28db8cbSShinas Rasheed static void octep_pfvf_set_offloads(struct octep_device *oct, u32 vf_id,
222e28db8cbSShinas Rasheed 				    union octep_pfvf_mbox_word cmd,
223e28db8cbSShinas Rasheed 				    union octep_pfvf_mbox_word *rsp)
224e28db8cbSShinas Rasheed {
225e28db8cbSShinas Rasheed 	struct octep_ctrl_net_offloads offloads = {
226e28db8cbSShinas Rasheed 		.rx_offloads = cmd.s_offloads.rx_ol_flags,
227e28db8cbSShinas Rasheed 		.tx_offloads = cmd.s_offloads.tx_ol_flags
228e28db8cbSShinas Rasheed 	};
229e28db8cbSShinas Rasheed 	int err;
230e28db8cbSShinas Rasheed 
231e28db8cbSShinas Rasheed 	err = octep_ctrl_net_set_offloads(oct, vf_id, &offloads, true);
232e28db8cbSShinas Rasheed 	if (err) {
233e28db8cbSShinas Rasheed 		rsp->s_offloads.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
234e28db8cbSShinas Rasheed 		dev_err(&oct->pdev->dev, "Set VF offloads failed via host control Mbox\n");
235e28db8cbSShinas Rasheed 		return;
236e28db8cbSShinas Rasheed 	}
237e28db8cbSShinas Rasheed 	rsp->s_offloads.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
238e28db8cbSShinas Rasheed }
239e28db8cbSShinas Rasheed 
octep_setup_pfvf_mbox(struct octep_device * oct)240cde29af9SShinas Rasheed int octep_setup_pfvf_mbox(struct octep_device *oct)
241cde29af9SShinas Rasheed {
242cde29af9SShinas Rasheed 	int i = 0, num_vfs = 0, rings_per_vf = 0;
243cde29af9SShinas Rasheed 	int ring = 0;
244cde29af9SShinas Rasheed 
245cde29af9SShinas Rasheed 	num_vfs = oct->conf->sriov_cfg.active_vfs;
246cde29af9SShinas Rasheed 	rings_per_vf = oct->conf->sriov_cfg.max_rings_per_vf;
247cde29af9SShinas Rasheed 
248cde29af9SShinas Rasheed 	for (i = 0; i < num_vfs; i++) {
249cde29af9SShinas Rasheed 		ring  = rings_per_vf * i;
250cde29af9SShinas Rasheed 		oct->mbox[ring] = vzalloc(sizeof(*oct->mbox[ring]));
251cde29af9SShinas Rasheed 
252cde29af9SShinas Rasheed 		if (!oct->mbox[ring])
253cde29af9SShinas Rasheed 			goto free_mbox;
254cde29af9SShinas Rasheed 
255cde29af9SShinas Rasheed 		memset(oct->mbox[ring], 0, sizeof(struct octep_mbox));
256c130e589SShinas Rasheed 		memset(&oct->vf_info[i], 0, sizeof(struct octep_pfvf_info));
257cde29af9SShinas Rasheed 		mutex_init(&oct->mbox[ring]->lock);
258cde29af9SShinas Rasheed 		INIT_WORK(&oct->mbox[ring]->wk.work, octep_pfvf_mbox_work);
259cde29af9SShinas Rasheed 		oct->mbox[ring]->wk.ctxptr = oct->mbox[ring];
260cde29af9SShinas Rasheed 		oct->mbox[ring]->oct = oct;
261cde29af9SShinas Rasheed 		oct->mbox[ring]->vf_id = i;
262cde29af9SShinas Rasheed 		oct->hw_ops.setup_mbox_regs(oct, ring);
263cde29af9SShinas Rasheed 	}
264cde29af9SShinas Rasheed 	return 0;
265cde29af9SShinas Rasheed 
266cde29af9SShinas Rasheed free_mbox:
267cde29af9SShinas Rasheed 	while (i) {
268cde29af9SShinas Rasheed 		i--;
269cde29af9SShinas Rasheed 		ring  = rings_per_vf * i;
270cde29af9SShinas Rasheed 		cancel_work_sync(&oct->mbox[ring]->wk.work);
271cde29af9SShinas Rasheed 		mutex_destroy(&oct->mbox[ring]->lock);
272cde29af9SShinas Rasheed 		vfree(oct->mbox[ring]);
273cde29af9SShinas Rasheed 		oct->mbox[ring] = NULL;
274cde29af9SShinas Rasheed 	}
275cde29af9SShinas Rasheed 	return -ENOMEM;
276cde29af9SShinas Rasheed }
277cde29af9SShinas Rasheed 
octep_delete_pfvf_mbox(struct octep_device * oct)278cde29af9SShinas Rasheed void octep_delete_pfvf_mbox(struct octep_device *oct)
279cde29af9SShinas Rasheed {
280cde29af9SShinas Rasheed 	int rings_per_vf = oct->conf->sriov_cfg.max_rings_per_vf;
281cde29af9SShinas Rasheed 	int num_vfs = oct->conf->sriov_cfg.active_vfs;
282cde29af9SShinas Rasheed 	int i = 0, ring = 0, vf_srn = 0;
283cde29af9SShinas Rasheed 
284cde29af9SShinas Rasheed 	for (i = 0; i < num_vfs; i++) {
285cde29af9SShinas Rasheed 		ring  = vf_srn + rings_per_vf * i;
286cde29af9SShinas Rasheed 		if (!oct->mbox[ring])
287cde29af9SShinas Rasheed 			continue;
288cde29af9SShinas Rasheed 
289cde29af9SShinas Rasheed 		if (work_pending(&oct->mbox[ring]->wk.work))
290cde29af9SShinas Rasheed 			cancel_work_sync(&oct->mbox[ring]->wk.work);
291cde29af9SShinas Rasheed 
292cde29af9SShinas Rasheed 		mutex_destroy(&oct->mbox[ring]->lock);
293cde29af9SShinas Rasheed 		vfree(oct->mbox[ring]);
294cde29af9SShinas Rasheed 		oct->mbox[ring] = NULL;
295cde29af9SShinas Rasheed 	}
296cde29af9SShinas Rasheed }
297cde29af9SShinas Rasheed 
octep_pfvf_pf_get_data(struct octep_device * oct,struct octep_mbox * mbox,int vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)298cde29af9SShinas Rasheed static void octep_pfvf_pf_get_data(struct octep_device *oct,
299cde29af9SShinas Rasheed 				   struct octep_mbox *mbox, int vf_id,
300cde29af9SShinas Rasheed 				   union octep_pfvf_mbox_word cmd,
301cde29af9SShinas Rasheed 				   union octep_pfvf_mbox_word *rsp)
302cde29af9SShinas Rasheed {
303cde29af9SShinas Rasheed 	int length = 0;
304cde29af9SShinas Rasheed 	int i = 0;
305cde29af9SShinas Rasheed 	int err;
306cde29af9SShinas Rasheed 	struct octep_iface_link_info link_info;
307cde29af9SShinas Rasheed 	struct octep_iface_rx_stats rx_stats;
308cde29af9SShinas Rasheed 	struct octep_iface_tx_stats tx_stats;
309cde29af9SShinas Rasheed 
310cde29af9SShinas Rasheed 	rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
311cde29af9SShinas Rasheed 
312cde29af9SShinas Rasheed 	if (cmd.s_data.frag != OCTEP_PFVF_MBOX_MORE_FRAG_FLAG) {
313cde29af9SShinas Rasheed 		mbox->config_data_index = 0;
314cde29af9SShinas Rasheed 		memset(mbox->config_data, 0, MAX_VF_PF_MBOX_DATA_SIZE);
315cde29af9SShinas Rasheed 		/* Based on the OPCODE CMD the PF driver
316cde29af9SShinas Rasheed 		 * specific API should be called to fetch
317cde29af9SShinas Rasheed 		 * the requested data
318cde29af9SShinas Rasheed 		 */
319cde29af9SShinas Rasheed 		switch (cmd.s.opcode) {
320cde29af9SShinas Rasheed 		case OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO:
321cde29af9SShinas Rasheed 			memset(&link_info, 0, sizeof(link_info));
322cde29af9SShinas Rasheed 			err = octep_ctrl_net_get_link_info(oct, vf_id, &link_info);
323cde29af9SShinas Rasheed 			if (!err) {
324cde29af9SShinas Rasheed 				mbox->message_len = sizeof(link_info);
325cde29af9SShinas Rasheed 				*((int32_t *)rsp->s_data.data) = mbox->message_len;
326cde29af9SShinas Rasheed 				memcpy(mbox->config_data, (u8 *)&link_info, sizeof(link_info));
327cde29af9SShinas Rasheed 			} else {
328cde29af9SShinas Rasheed 				rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
329cde29af9SShinas Rasheed 				return;
330cde29af9SShinas Rasheed 			}
331cde29af9SShinas Rasheed 			break;
332cde29af9SShinas Rasheed 		case OCTEP_PFVF_MBOX_CMD_GET_STATS:
333cde29af9SShinas Rasheed 			memset(&rx_stats, 0, sizeof(rx_stats));
334cde29af9SShinas Rasheed 			memset(&tx_stats, 0, sizeof(tx_stats));
335cde29af9SShinas Rasheed 			err = octep_ctrl_net_get_if_stats(oct, vf_id, &rx_stats, &tx_stats);
336cde29af9SShinas Rasheed 			if (!err) {
337cde29af9SShinas Rasheed 				mbox->message_len = sizeof(rx_stats) + sizeof(tx_stats);
338cde29af9SShinas Rasheed 				*((int32_t *)rsp->s_data.data) = mbox->message_len;
339cde29af9SShinas Rasheed 				memcpy(mbox->config_data, (u8 *)&rx_stats, sizeof(rx_stats));
340cde29af9SShinas Rasheed 				memcpy(mbox->config_data + sizeof(rx_stats), (u8 *)&tx_stats,
341cde29af9SShinas Rasheed 				       sizeof(tx_stats));
342cde29af9SShinas Rasheed 
343cde29af9SShinas Rasheed 			} else {
344cde29af9SShinas Rasheed 				rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
345cde29af9SShinas Rasheed 				return;
346cde29af9SShinas Rasheed 			}
347cde29af9SShinas Rasheed 			break;
348cde29af9SShinas Rasheed 		}
349cde29af9SShinas Rasheed 		*((int32_t *)rsp->s_data.data) = mbox->message_len;
350cde29af9SShinas Rasheed 		return;
351cde29af9SShinas Rasheed 	}
352cde29af9SShinas Rasheed 
353cde29af9SShinas Rasheed 	if (mbox->message_len > OCTEP_PFVF_MBOX_MAX_DATA_SIZE)
354cde29af9SShinas Rasheed 		length = OCTEP_PFVF_MBOX_MAX_DATA_SIZE;
355cde29af9SShinas Rasheed 	else
356cde29af9SShinas Rasheed 		length = mbox->message_len;
357cde29af9SShinas Rasheed 
358cde29af9SShinas Rasheed 	mbox->message_len -= length;
359cde29af9SShinas Rasheed 
360cde29af9SShinas Rasheed 	for (i = 0; i < length; i++) {
361cde29af9SShinas Rasheed 		rsp->s_data.data[i] =
362cde29af9SShinas Rasheed 			mbox->config_data[mbox->config_data_index];
363cde29af9SShinas Rasheed 		mbox->config_data_index++;
364cde29af9SShinas Rasheed 	}
365cde29af9SShinas Rasheed }
366cde29af9SShinas Rasheed 
octep_pfvf_notify(struct octep_device * oct,struct octep_ctrl_mbox_msg * msg)3674ebb86a9SShinas Rasheed void octep_pfvf_notify(struct octep_device *oct, struct octep_ctrl_mbox_msg *msg)
3684ebb86a9SShinas Rasheed {
3694ebb86a9SShinas Rasheed 	union octep_pfvf_mbox_word notif = { 0 };
3704ebb86a9SShinas Rasheed 	struct octep_ctrl_net_f2h_req *req;
3714ebb86a9SShinas Rasheed 
3724ebb86a9SShinas Rasheed 	req = (struct octep_ctrl_net_f2h_req *)msg->sg_list[0].msg;
3734ebb86a9SShinas Rasheed 	switch (req->hdr.s.cmd) {
3744ebb86a9SShinas Rasheed 	case OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS:
3754ebb86a9SShinas Rasheed 		notif.s_link_status.opcode = OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS;
3764ebb86a9SShinas Rasheed 		notif.s_link_status.status = req->link.state;
3774ebb86a9SShinas Rasheed 		break;
3784ebb86a9SShinas Rasheed 	default:
3794ebb86a9SShinas Rasheed 		pr_info("Unknown mbox notif for vf: %u\n",
3804ebb86a9SShinas Rasheed 			req->hdr.s.cmd);
3814ebb86a9SShinas Rasheed 		return;
3824ebb86a9SShinas Rasheed 	}
3834ebb86a9SShinas Rasheed 
3844ebb86a9SShinas Rasheed 	notif.s.type = OCTEP_PFVF_MBOX_TYPE_CMD;
3854ebb86a9SShinas Rasheed 	octep_send_notification(oct, msg->hdr.s.vf_idx, notif);
3864ebb86a9SShinas Rasheed }
3874ebb86a9SShinas Rasheed 
octep_pfvf_mbox_work(struct work_struct * work)388cde29af9SShinas Rasheed void octep_pfvf_mbox_work(struct work_struct *work)
389cde29af9SShinas Rasheed {
390cde29af9SShinas Rasheed 	struct octep_pfvf_mbox_wk *wk = container_of(work, struct octep_pfvf_mbox_wk, work);
391cde29af9SShinas Rasheed 	union octep_pfvf_mbox_word cmd = { 0 };
392cde29af9SShinas Rasheed 	union octep_pfvf_mbox_word rsp = { 0 };
393cde29af9SShinas Rasheed 	struct octep_mbox *mbox = NULL;
394cde29af9SShinas Rasheed 	struct octep_device *oct = NULL;
395cde29af9SShinas Rasheed 	int vf_id;
396cde29af9SShinas Rasheed 
397cde29af9SShinas Rasheed 	mbox = (struct octep_mbox *)wk->ctxptr;
398cde29af9SShinas Rasheed 	oct = (struct octep_device *)mbox->oct;
399cde29af9SShinas Rasheed 	vf_id = mbox->vf_id;
400cde29af9SShinas Rasheed 
401cde29af9SShinas Rasheed 	mutex_lock(&mbox->lock);
402cde29af9SShinas Rasheed 	cmd.u64 = readq(mbox->vf_pf_data_reg);
403cde29af9SShinas Rasheed 	rsp.u64 = 0;
404cde29af9SShinas Rasheed 
405cde29af9SShinas Rasheed 	switch (cmd.s.opcode) {
406cde29af9SShinas Rasheed 	case OCTEP_PFVF_MBOX_CMD_VERSION:
407cde29af9SShinas Rasheed 		octep_pfvf_validate_version(oct, vf_id, cmd, &rsp);
408cde29af9SShinas Rasheed 		break;
409cde29af9SShinas Rasheed 	case OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS:
410cde29af9SShinas Rasheed 		octep_pfvf_get_link_status(oct, vf_id, cmd, &rsp);
411cde29af9SShinas Rasheed 		break;
412cde29af9SShinas Rasheed 	case OCTEP_PFVF_MBOX_CMD_SET_LINK_STATUS:
413cde29af9SShinas Rasheed 		octep_pfvf_set_link_status(oct, vf_id, cmd, &rsp);
414cde29af9SShinas Rasheed 		break;
415cde29af9SShinas Rasheed 	case OCTEP_PFVF_MBOX_CMD_SET_RX_STATE:
416cde29af9SShinas Rasheed 		octep_pfvf_set_rx_state(oct, vf_id, cmd, &rsp);
417cde29af9SShinas Rasheed 		break;
418cde29af9SShinas Rasheed 	case OCTEP_PFVF_MBOX_CMD_SET_MTU:
419cde29af9SShinas Rasheed 		octep_pfvf_set_mtu(oct, vf_id, cmd, &rsp);
420cde29af9SShinas Rasheed 		break;
421cde29af9SShinas Rasheed 	case OCTEP_PFVF_MBOX_CMD_SET_MAC_ADDR:
422cde29af9SShinas Rasheed 		octep_pfvf_set_mac_addr(oct, vf_id, cmd, &rsp);
423cde29af9SShinas Rasheed 		break;
424cde29af9SShinas Rasheed 	case OCTEP_PFVF_MBOX_CMD_GET_MAC_ADDR:
425cde29af9SShinas Rasheed 		octep_pfvf_get_mac_addr(oct, vf_id, cmd, &rsp);
426cde29af9SShinas Rasheed 		break;
427cde29af9SShinas Rasheed 	case OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO:
428cde29af9SShinas Rasheed 	case OCTEP_PFVF_MBOX_CMD_GET_STATS:
429cde29af9SShinas Rasheed 		octep_pfvf_pf_get_data(oct, mbox, vf_id, cmd, &rsp);
430cde29af9SShinas Rasheed 		break;
431cde29af9SShinas Rasheed 	case OCTEP_PFVF_MBOX_CMD_GET_MTU:
432cde29af9SShinas Rasheed 		octep_pfvf_get_mtu(oct, vf_id, cmd, &rsp);
433cde29af9SShinas Rasheed 		break;
434cde29af9SShinas Rasheed 	case OCTEP_PFVF_MBOX_CMD_DEV_REMOVE:
435cde29af9SShinas Rasheed 		octep_pfvf_dev_remove(oct, vf_id, cmd, &rsp);
436cde29af9SShinas Rasheed 		break;
437e28db8cbSShinas Rasheed 	case OCTEP_PFVF_MBOX_CMD_GET_FW_INFO:
438e28db8cbSShinas Rasheed 		octep_pfvf_get_fw_info(oct, vf_id, cmd, &rsp);
439e28db8cbSShinas Rasheed 		break;
440e28db8cbSShinas Rasheed 	case OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS:
441e28db8cbSShinas Rasheed 		octep_pfvf_set_offloads(oct, vf_id, cmd, &rsp);
442e28db8cbSShinas Rasheed 		break;
443cde29af9SShinas Rasheed 	default:
444cde29af9SShinas Rasheed 		dev_err(&oct->pdev->dev, "PF-VF mailbox: invalid opcode %d\n", cmd.s.opcode);
445cde29af9SShinas Rasheed 		rsp.s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
446cde29af9SShinas Rasheed 		break;
447cde29af9SShinas Rasheed 	}
448cde29af9SShinas Rasheed 	writeq(rsp.u64, mbox->vf_pf_data_reg);
449cde29af9SShinas Rasheed 	mutex_unlock(&mbox->lock);
450cde29af9SShinas Rasheed }
451