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