1 // SPDX-License-Identifier: GPL-2.0
2 /* Marvell Octeon EP (EndPoint) Ethernet Driver
4 * Copyright (C) 2020 Marvell.
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>
16 #include <linux/pci.h>
17 #include <linux/etherdevice.h>
19 #include "octep_config.h"
20 #include "octep_main.h"
21 #include "octep_pfvf_mbox.h"
22 #include "octep_ctrl_net.h"
24 /* When a new command is implemented, the below table should be updated
25 * with new command and it's version info.
27 static u32 pfvf_cmd_versions[OCTEP_PFVF_MBOX_CMD_MAX] = {
28 [0 ... OCTEP_PFVF_MBOX_CMD_DEV_REMOVE] = OCTEP_PFVF_MBOX_VERSION_V1,
29 [OCTEP_PFVF_MBOX_CMD_GET_FW_INFO ... OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS] =
30 OCTEP_PFVF_MBOX_VERSION_V2
33 static void octep_pfvf_validate_version(struct octep_device *oct, u32 vf_id,
34 union octep_pfvf_mbox_word cmd,
35 union octep_pfvf_mbox_word *rsp)
37 u32 vf_version = (u32)cmd.s_version.version;
39 dev_dbg(&oct->pdev->dev, "VF id:%d VF version:%d PF version:%d\n",
40 vf_id, vf_version, OCTEP_PFVF_MBOX_VERSION_CURRENT);
41 if (vf_version < OCTEP_PFVF_MBOX_VERSION_CURRENT)
42 rsp->s_version.version = vf_version;
44 rsp->s_version.version = OCTEP_PFVF_MBOX_VERSION_CURRENT;
46 oct->vf_info[vf_id].mbox_version = rsp->s_version.version;
47 dev_dbg(&oct->pdev->dev, "VF id:%d negotiated VF version:%d\n",
48 vf_id, oct->vf_info[vf_id].mbox_version);
50 rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
53 static void octep_pfvf_get_link_status(struct octep_device *oct, u32 vf_id,
54 union octep_pfvf_mbox_word cmd,
55 union octep_pfvf_mbox_word *rsp)
59 status = octep_ctrl_net_get_link_status(oct, vf_id);
61 rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
62 dev_err(&oct->pdev->dev, "Get VF link status failed via host control Mbox\n");
65 rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
66 rsp->s_link_status.status = status;
69 static void octep_pfvf_set_link_status(struct octep_device *oct, u32 vf_id,
70 union octep_pfvf_mbox_word cmd,
71 union octep_pfvf_mbox_word *rsp)
75 err = octep_ctrl_net_set_link_status(oct, vf_id, cmd.s_link_status.status, true);
77 rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
78 dev_err(&oct->pdev->dev, "Set VF link status failed via host control Mbox\n");
81 rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
84 static void octep_pfvf_set_rx_state(struct octep_device *oct, u32 vf_id,
85 union octep_pfvf_mbox_word cmd,
86 union octep_pfvf_mbox_word *rsp)
90 err = octep_ctrl_net_set_rx_state(oct, vf_id, cmd.s_link_state.state, true);
92 rsp->s_link_state.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
93 dev_err(&oct->pdev->dev, "Set VF Rx link state failed via host control Mbox\n");
96 rsp->s_link_state.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
99 static int octep_send_notification(struct octep_device *oct, u32 vf_id,
100 union octep_pfvf_mbox_word cmd)
102 u32 max_rings_per_vf, vf_mbox_queue;
103 struct octep_mbox *mbox;
105 /* check if VF PF Mailbox is compatible for this notification */
106 if (pfvf_cmd_versions[cmd.s.opcode] > oct->vf_info[vf_id].mbox_version) {
107 dev_dbg(&oct->pdev->dev, "VF Mbox doesn't support Notification:%d on VF ver:%d\n",
108 cmd.s.opcode, oct->vf_info[vf_id].mbox_version);
112 max_rings_per_vf = CFG_GET_MAX_RPVF(oct->conf);
113 vf_mbox_queue = vf_id * max_rings_per_vf;
114 if (!oct->mbox[vf_mbox_queue]) {
115 dev_err(&oct->pdev->dev, "Notif obtained for bad mbox vf %d\n", vf_id);
118 mbox = oct->mbox[vf_mbox_queue];
120 mutex_lock(&mbox->lock);
121 writeq(cmd.u64, mbox->pf_vf_data_reg);
122 mutex_unlock(&mbox->lock);
127 static void octep_pfvf_set_mtu(struct octep_device *oct, u32 vf_id,
128 union octep_pfvf_mbox_word cmd,
129 union octep_pfvf_mbox_word *rsp)
133 err = octep_ctrl_net_set_mtu(oct, vf_id, cmd.s_set_mtu.mtu, true);
135 rsp->s_set_mtu.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
136 dev_err(&oct->pdev->dev, "Set VF MTU failed via host control Mbox\n");
139 rsp->s_set_mtu.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
142 static void octep_pfvf_get_mtu(struct octep_device *oct, u32 vf_id,
143 union octep_pfvf_mbox_word cmd,
144 union octep_pfvf_mbox_word *rsp)
146 int max_rx_pktlen = oct->netdev->max_mtu + (ETH_HLEN + ETH_FCS_LEN);
148 rsp->s_set_mtu.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
149 rsp->s_get_mtu.mtu = max_rx_pktlen;
152 static void octep_pfvf_set_mac_addr(struct octep_device *oct, u32 vf_id,
153 union octep_pfvf_mbox_word cmd,
154 union octep_pfvf_mbox_word *rsp)
158 err = octep_ctrl_net_set_mac_addr(oct, vf_id, cmd.s_set_mac.mac_addr, true);
160 rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
161 dev_err(&oct->pdev->dev, "Set VF MAC address failed via host control Mbox\n");
164 rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
167 static void octep_pfvf_get_mac_addr(struct octep_device *oct, u32 vf_id,
168 union octep_pfvf_mbox_word cmd,
169 union octep_pfvf_mbox_word *rsp)
173 err = octep_ctrl_net_get_mac_addr(oct, vf_id, rsp->s_set_mac.mac_addr);
175 rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
176 dev_err(&oct->pdev->dev, "Get VF MAC address failed via host control Mbox\n");
179 rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
182 static void octep_pfvf_dev_remove(struct octep_device *oct, u32 vf_id,
183 union octep_pfvf_mbox_word cmd,
184 union octep_pfvf_mbox_word *rsp)
188 err = octep_ctrl_net_dev_remove(oct, vf_id);
190 rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
191 dev_err(&oct->pdev->dev, "Failed to acknowledge fw of vf %d removal\n",
195 rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
198 static void octep_pfvf_get_fw_info(struct octep_device *oct, u32 vf_id,
199 union octep_pfvf_mbox_word cmd,
200 union octep_pfvf_mbox_word *rsp)
202 struct octep_fw_info fw_info;
205 err = octep_ctrl_net_get_info(oct, vf_id, &fw_info);
207 rsp->s_fw_info.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
208 dev_err(&oct->pdev->dev, "Get VF info failed via host control Mbox\n");
212 rsp->s_fw_info.pkind = fw_info.pkind;
213 rsp->s_fw_info.fsz = fw_info.fsz;
214 rsp->s_fw_info.rx_ol_flags = fw_info.rx_ol_flags;
215 rsp->s_fw_info.tx_ol_flags = fw_info.tx_ol_flags;
217 rsp->s_fw_info.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
220 static void octep_pfvf_set_offloads(struct octep_device *oct, u32 vf_id,
221 union octep_pfvf_mbox_word cmd,
222 union octep_pfvf_mbox_word *rsp)
224 struct octep_ctrl_net_offloads offloads = {
225 .rx_offloads = cmd.s_offloads.rx_ol_flags,
226 .tx_offloads = cmd.s_offloads.tx_ol_flags
230 err = octep_ctrl_net_set_offloads(oct, vf_id, &offloads, true);
232 rsp->s_offloads.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
233 dev_err(&oct->pdev->dev, "Set VF offloads failed via host control Mbox\n");
236 rsp->s_offloads.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
239 int octep_setup_pfvf_mbox(struct octep_device *oct)
241 int i = 0, num_vfs = 0, rings_per_vf = 0;
244 num_vfs = oct->conf->sriov_cfg.active_vfs;
245 rings_per_vf = oct->conf->sriov_cfg.max_rings_per_vf;
247 for (i = 0; i < num_vfs; i++) {
248 ring = rings_per_vf * i;
249 oct->mbox[ring] = vzalloc(sizeof(*oct->mbox[ring]));
251 if (!oct->mbox[ring])
254 memset(oct->mbox[ring], 0, sizeof(struct octep_mbox));
255 memset(&oct->vf_info[i], 0, sizeof(struct octep_pfvf_info));
256 mutex_init(&oct->mbox[ring]->lock);
257 INIT_WORK(&oct->mbox[ring]->wk.work, octep_pfvf_mbox_work);
258 oct->mbox[ring]->wk.ctxptr = oct->mbox[ring];
259 oct->mbox[ring]->oct = oct;
260 oct->mbox[ring]->vf_id = i;
261 oct->hw_ops.setup_mbox_regs(oct, ring);
268 ring = rings_per_vf * i;
269 cancel_work_sync(&oct->mbox[ring]->wk.work);
270 mutex_destroy(&oct->mbox[ring]->lock);
271 vfree(oct->mbox[ring]);
272 oct->mbox[ring] = NULL;
277 void octep_delete_pfvf_mbox(struct octep_device *oct)
279 int rings_per_vf = oct->conf->sriov_cfg.max_rings_per_vf;
280 int num_vfs = oct->conf->sriov_cfg.active_vfs;
281 int i = 0, ring = 0, vf_srn = 0;
283 for (i = 0; i < num_vfs; i++) {
284 ring = vf_srn + rings_per_vf * i;
285 if (!oct->mbox[ring])
288 if (work_pending(&oct->mbox[ring]->wk.work))
289 cancel_work_sync(&oct->mbox[ring]->wk.work);
291 mutex_destroy(&oct->mbox[ring]->lock);
292 vfree(oct->mbox[ring]);
293 oct->mbox[ring] = NULL;
297 static void octep_pfvf_pf_get_data(struct octep_device *oct,
298 struct octep_mbox *mbox, int vf_id,
299 union octep_pfvf_mbox_word cmd,
300 union octep_pfvf_mbox_word *rsp)
305 struct octep_iface_link_info link_info;
306 struct octep_iface_rx_stats rx_stats;
307 struct octep_iface_tx_stats tx_stats;
309 rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
311 if (cmd.s_data.frag != OCTEP_PFVF_MBOX_MORE_FRAG_FLAG) {
312 mbox->config_data_index = 0;
313 memset(mbox->config_data, 0, MAX_VF_PF_MBOX_DATA_SIZE);
314 /* Based on the OPCODE CMD the PF driver
315 * specific API should be called to fetch
318 switch (cmd.s.opcode) {
319 case OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO:
320 memset(&link_info, 0, sizeof(link_info));
321 err = octep_ctrl_net_get_link_info(oct, vf_id, &link_info);
323 mbox->message_len = sizeof(link_info);
324 *((int32_t *)rsp->s_data.data) = mbox->message_len;
325 memcpy(mbox->config_data, (u8 *)&link_info, sizeof(link_info));
327 rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
331 case OCTEP_PFVF_MBOX_CMD_GET_STATS:
332 memset(&rx_stats, 0, sizeof(rx_stats));
333 memset(&tx_stats, 0, sizeof(tx_stats));
334 err = octep_ctrl_net_get_if_stats(oct, vf_id, &rx_stats, &tx_stats);
336 mbox->message_len = sizeof(rx_stats) + sizeof(tx_stats);
337 *((int32_t *)rsp->s_data.data) = mbox->message_len;
338 memcpy(mbox->config_data, (u8 *)&rx_stats, sizeof(rx_stats));
339 memcpy(mbox->config_data + sizeof(rx_stats), (u8 *)&tx_stats,
343 rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
348 *((int32_t *)rsp->s_data.data) = mbox->message_len;
352 if (mbox->message_len > OCTEP_PFVF_MBOX_MAX_DATA_SIZE)
353 length = OCTEP_PFVF_MBOX_MAX_DATA_SIZE;
355 length = mbox->message_len;
357 mbox->message_len -= length;
359 for (i = 0; i < length; i++) {
360 rsp->s_data.data[i] =
361 mbox->config_data[mbox->config_data_index];
362 mbox->config_data_index++;
366 void octep_pfvf_notify(struct octep_device *oct, struct octep_ctrl_mbox_msg *msg)
368 union octep_pfvf_mbox_word notif = { 0 };
369 struct octep_ctrl_net_f2h_req *req;
371 req = (struct octep_ctrl_net_f2h_req *)msg->sg_list[0].msg;
372 switch (req->hdr.s.cmd) {
373 case OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS:
374 notif.s_link_status.opcode = OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS;
375 notif.s_link_status.status = req->link.state;
378 pr_info("Unknown mbox notif for vf: %u\n",
383 notif.s.type = OCTEP_PFVF_MBOX_TYPE_CMD;
384 octep_send_notification(oct, msg->hdr.s.vf_idx, notif);
387 void octep_pfvf_mbox_work(struct work_struct *work)
389 struct octep_pfvf_mbox_wk *wk = container_of(work, struct octep_pfvf_mbox_wk, work);
390 union octep_pfvf_mbox_word cmd = { 0 };
391 union octep_pfvf_mbox_word rsp = { 0 };
392 struct octep_mbox *mbox = NULL;
393 struct octep_device *oct = NULL;
396 mbox = (struct octep_mbox *)wk->ctxptr;
397 oct = (struct octep_device *)mbox->oct;
400 mutex_lock(&mbox->lock);
401 cmd.u64 = readq(mbox->vf_pf_data_reg);
404 switch (cmd.s.opcode) {
405 case OCTEP_PFVF_MBOX_CMD_VERSION:
406 octep_pfvf_validate_version(oct, vf_id, cmd, &rsp);
408 case OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS:
409 octep_pfvf_get_link_status(oct, vf_id, cmd, &rsp);
411 case OCTEP_PFVF_MBOX_CMD_SET_LINK_STATUS:
412 octep_pfvf_set_link_status(oct, vf_id, cmd, &rsp);
414 case OCTEP_PFVF_MBOX_CMD_SET_RX_STATE:
415 octep_pfvf_set_rx_state(oct, vf_id, cmd, &rsp);
417 case OCTEP_PFVF_MBOX_CMD_SET_MTU:
418 octep_pfvf_set_mtu(oct, vf_id, cmd, &rsp);
420 case OCTEP_PFVF_MBOX_CMD_SET_MAC_ADDR:
421 octep_pfvf_set_mac_addr(oct, vf_id, cmd, &rsp);
423 case OCTEP_PFVF_MBOX_CMD_GET_MAC_ADDR:
424 octep_pfvf_get_mac_addr(oct, vf_id, cmd, &rsp);
426 case OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO:
427 case OCTEP_PFVF_MBOX_CMD_GET_STATS:
428 octep_pfvf_pf_get_data(oct, mbox, vf_id, cmd, &rsp);
430 case OCTEP_PFVF_MBOX_CMD_GET_MTU:
431 octep_pfvf_get_mtu(oct, vf_id, cmd, &rsp);
433 case OCTEP_PFVF_MBOX_CMD_DEV_REMOVE:
434 octep_pfvf_dev_remove(oct, vf_id, cmd, &rsp);
436 case OCTEP_PFVF_MBOX_CMD_GET_FW_INFO:
437 octep_pfvf_get_fw_info(oct, vf_id, cmd, &rsp);
439 case OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS:
440 octep_pfvf_set_offloads(oct, vf_id, cmd, &rsp);
443 dev_err(&oct->pdev->dev, "PF-VF mailbox: invalid opcode %d\n", cmd.s.opcode);
444 rsp.s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
447 writeq(rsp.u64, mbox->vf_pf_data_reg);
448 mutex_unlock(&mbox->lock);