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 rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
200 }
201
octep_pfvf_dev_remove(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)202 static void octep_pfvf_dev_remove(struct octep_device *oct, u32 vf_id,
203 union octep_pfvf_mbox_word cmd,
204 union octep_pfvf_mbox_word *rsp)
205 {
206 int err;
207
208 err = octep_ctrl_net_dev_remove(oct, vf_id);
209 if (err) {
210 rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
211 dev_err(&oct->pdev->dev, "Failed to acknowledge fw of vf %d removal\n",
212 vf_id);
213 return;
214 }
215 rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
216 }
217
octep_pfvf_get_fw_info(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)218 static void octep_pfvf_get_fw_info(struct octep_device *oct, u32 vf_id,
219 union octep_pfvf_mbox_word cmd,
220 union octep_pfvf_mbox_word *rsp)
221 {
222 struct octep_fw_info fw_info;
223 int err;
224
225 err = octep_ctrl_net_get_info(oct, vf_id, &fw_info);
226 if (err) {
227 rsp->s_fw_info.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
228 dev_err(&oct->pdev->dev, "Get VF info failed via host control Mbox\n");
229 return;
230 }
231
232 rsp->s_fw_info.pkind = fw_info.pkind;
233 rsp->s_fw_info.fsz = fw_info.fsz;
234 rsp->s_fw_info.rx_ol_flags = fw_info.rx_ol_flags;
235 rsp->s_fw_info.tx_ol_flags = fw_info.tx_ol_flags;
236
237 rsp->s_fw_info.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
238 }
239
octep_pfvf_set_offloads(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)240 static void octep_pfvf_set_offloads(struct octep_device *oct, u32 vf_id,
241 union octep_pfvf_mbox_word cmd,
242 union octep_pfvf_mbox_word *rsp)
243 {
244 struct octep_ctrl_net_offloads offloads = {
245 .rx_offloads = cmd.s_offloads.rx_ol_flags,
246 .tx_offloads = cmd.s_offloads.tx_ol_flags
247 };
248 int err;
249
250 err = octep_ctrl_net_set_offloads(oct, vf_id, &offloads, true);
251 if (err) {
252 rsp->s_offloads.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
253 dev_err(&oct->pdev->dev, "Set VF offloads failed via host control Mbox\n");
254 return;
255 }
256 rsp->s_offloads.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
257 }
258
octep_setup_pfvf_mbox(struct octep_device * oct)259 int octep_setup_pfvf_mbox(struct octep_device *oct)
260 {
261 int i = 0, num_vfs = 0, rings_per_vf = 0;
262 int ring = 0;
263
264 num_vfs = oct->conf->sriov_cfg.active_vfs;
265 rings_per_vf = oct->conf->sriov_cfg.max_rings_per_vf;
266
267 for (i = 0; i < num_vfs; i++) {
268 ring = rings_per_vf * i;
269 oct->mbox[ring] = vzalloc(sizeof(*oct->mbox[ring]));
270
271 if (!oct->mbox[ring])
272 goto free_mbox;
273
274 memset(oct->mbox[ring], 0, sizeof(struct octep_mbox));
275 memset(&oct->vf_info[i], 0, sizeof(struct octep_pfvf_info));
276 mutex_init(&oct->mbox[ring]->lock);
277 INIT_WORK(&oct->mbox[ring]->wk.work, octep_pfvf_mbox_work);
278 oct->mbox[ring]->wk.ctxptr = oct->mbox[ring];
279 oct->mbox[ring]->oct = oct;
280 oct->mbox[ring]->vf_id = i;
281 oct->hw_ops.setup_mbox_regs(oct, ring);
282 }
283 return 0;
284
285 free_mbox:
286 while (i) {
287 i--;
288 ring = rings_per_vf * i;
289 cancel_work_sync(&oct->mbox[ring]->wk.work);
290 mutex_destroy(&oct->mbox[ring]->lock);
291 vfree(oct->mbox[ring]);
292 oct->mbox[ring] = NULL;
293 }
294 return -ENOMEM;
295 }
296
octep_delete_pfvf_mbox(struct octep_device * oct)297 void octep_delete_pfvf_mbox(struct octep_device *oct)
298 {
299 int rings_per_vf = oct->conf->sriov_cfg.max_rings_per_vf;
300 int num_vfs = oct->conf->sriov_cfg.active_vfs;
301 int i = 0, ring = 0, vf_srn = 0;
302
303 for (i = 0; i < num_vfs; i++) {
304 ring = vf_srn + rings_per_vf * i;
305 if (!oct->mbox[ring])
306 continue;
307
308 if (work_pending(&oct->mbox[ring]->wk.work))
309 cancel_work_sync(&oct->mbox[ring]->wk.work);
310
311 mutex_destroy(&oct->mbox[ring]->lock);
312 vfree(oct->mbox[ring]);
313 oct->mbox[ring] = NULL;
314 }
315 }
316
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)317 static void octep_pfvf_pf_get_data(struct octep_device *oct,
318 struct octep_mbox *mbox, int vf_id,
319 union octep_pfvf_mbox_word cmd,
320 union octep_pfvf_mbox_word *rsp)
321 {
322 int length = 0;
323 int i = 0;
324 int err;
325 struct octep_iface_link_info link_info;
326 struct octep_iface_rx_stats rx_stats;
327 struct octep_iface_tx_stats tx_stats;
328
329 rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
330
331 if (cmd.s_data.frag != OCTEP_PFVF_MBOX_MORE_FRAG_FLAG) {
332 mbox->config_data_index = 0;
333 memset(mbox->config_data, 0, MAX_VF_PF_MBOX_DATA_SIZE);
334 /* Based on the OPCODE CMD the PF driver
335 * specific API should be called to fetch
336 * the requested data
337 */
338 switch (cmd.s.opcode) {
339 case OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO:
340 memset(&link_info, 0, sizeof(link_info));
341 err = octep_ctrl_net_get_link_info(oct, vf_id, &link_info);
342 if (!err) {
343 mbox->message_len = sizeof(link_info);
344 *((int32_t *)rsp->s_data.data) = mbox->message_len;
345 memcpy(mbox->config_data, (u8 *)&link_info, sizeof(link_info));
346 } else {
347 rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
348 return;
349 }
350 break;
351 case OCTEP_PFVF_MBOX_CMD_GET_STATS:
352 memset(&rx_stats, 0, sizeof(rx_stats));
353 memset(&tx_stats, 0, sizeof(tx_stats));
354 err = octep_ctrl_net_get_if_stats(oct, vf_id, &rx_stats, &tx_stats);
355 if (!err) {
356 mbox->message_len = sizeof(rx_stats) + sizeof(tx_stats);
357 *((int32_t *)rsp->s_data.data) = mbox->message_len;
358 memcpy(mbox->config_data, (u8 *)&rx_stats, sizeof(rx_stats));
359 memcpy(mbox->config_data + sizeof(rx_stats), (u8 *)&tx_stats,
360 sizeof(tx_stats));
361
362 } else {
363 rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
364 return;
365 }
366 break;
367 }
368 *((int32_t *)rsp->s_data.data) = mbox->message_len;
369 return;
370 }
371
372 if (mbox->message_len > OCTEP_PFVF_MBOX_MAX_DATA_SIZE)
373 length = OCTEP_PFVF_MBOX_MAX_DATA_SIZE;
374 else
375 length = mbox->message_len;
376
377 mbox->message_len -= length;
378
379 for (i = 0; i < length; i++) {
380 rsp->s_data.data[i] =
381 mbox->config_data[mbox->config_data_index];
382 mbox->config_data_index++;
383 }
384 }
385
octep_pfvf_notify(struct octep_device * oct,struct octep_ctrl_mbox_msg * msg)386 void octep_pfvf_notify(struct octep_device *oct, struct octep_ctrl_mbox_msg *msg)
387 {
388 union octep_pfvf_mbox_word notif = { 0 };
389 struct octep_ctrl_net_f2h_req *req;
390
391 req = (struct octep_ctrl_net_f2h_req *)msg->sg_list[0].msg;
392 switch (req->hdr.s.cmd) {
393 case OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS:
394 notif.s_link_status.opcode = OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS;
395 notif.s_link_status.status = req->link.state;
396 break;
397 default:
398 pr_info("Unknown mbox notif for vf: %u\n",
399 req->hdr.s.cmd);
400 return;
401 }
402
403 notif.s.type = OCTEP_PFVF_MBOX_TYPE_CMD;
404 octep_send_notification(oct, msg->hdr.s.vf_idx, notif);
405 }
406
octep_pfvf_mbox_work(struct work_struct * work)407 void octep_pfvf_mbox_work(struct work_struct *work)
408 {
409 struct octep_pfvf_mbox_wk *wk = container_of(work, struct octep_pfvf_mbox_wk, work);
410 union octep_pfvf_mbox_word cmd = { 0 };
411 union octep_pfvf_mbox_word rsp = { 0 };
412 struct octep_mbox *mbox = NULL;
413 struct octep_device *oct = NULL;
414 int vf_id;
415
416 mbox = (struct octep_mbox *)wk->ctxptr;
417 oct = (struct octep_device *)mbox->oct;
418 vf_id = mbox->vf_id;
419
420 mutex_lock(&mbox->lock);
421 cmd.u64 = readq(mbox->vf_pf_data_reg);
422 rsp.u64 = 0;
423
424 switch (cmd.s.opcode) {
425 case OCTEP_PFVF_MBOX_CMD_VERSION:
426 octep_pfvf_validate_version(oct, vf_id, cmd, &rsp);
427 break;
428 case OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS:
429 octep_pfvf_get_link_status(oct, vf_id, cmd, &rsp);
430 break;
431 case OCTEP_PFVF_MBOX_CMD_SET_LINK_STATUS:
432 octep_pfvf_set_link_status(oct, vf_id, cmd, &rsp);
433 break;
434 case OCTEP_PFVF_MBOX_CMD_SET_RX_STATE:
435 octep_pfvf_set_rx_state(oct, vf_id, cmd, &rsp);
436 break;
437 case OCTEP_PFVF_MBOX_CMD_SET_MTU:
438 octep_pfvf_set_mtu(oct, vf_id, cmd, &rsp);
439 break;
440 case OCTEP_PFVF_MBOX_CMD_SET_MAC_ADDR:
441 octep_pfvf_set_mac_addr(oct, vf_id, cmd, &rsp);
442 break;
443 case OCTEP_PFVF_MBOX_CMD_GET_MAC_ADDR:
444 octep_pfvf_get_mac_addr(oct, vf_id, cmd, &rsp);
445 break;
446 case OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO:
447 case OCTEP_PFVF_MBOX_CMD_GET_STATS:
448 octep_pfvf_pf_get_data(oct, mbox, vf_id, cmd, &rsp);
449 break;
450 case OCTEP_PFVF_MBOX_CMD_GET_MTU:
451 octep_pfvf_get_mtu(oct, vf_id, cmd, &rsp);
452 break;
453 case OCTEP_PFVF_MBOX_CMD_DEV_REMOVE:
454 octep_pfvf_dev_remove(oct, vf_id, cmd, &rsp);
455 break;
456 case OCTEP_PFVF_MBOX_CMD_GET_FW_INFO:
457 octep_pfvf_get_fw_info(oct, vf_id, cmd, &rsp);
458 break;
459 case OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS:
460 octep_pfvf_set_offloads(oct, vf_id, cmd, &rsp);
461 break;
462 default:
463 dev_err(&oct->pdev->dev, "PF-VF mailbox: invalid opcode %d\n", cmd.s.opcode);
464 rsp.s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
465 break;
466 }
467 writeq(rsp.u64, mbox->vf_pf_data_reg);
468 mutex_unlock(&mbox->lock);
469 }
470