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
19 #include "octep_config.h"
20 #include "octep_main.h"
21 #include "octep_pfvf_mbox.h"
22 #include "octep_ctrl_net.h"
23
24 /* When a new command is implemented, the below table should be updated
25 * with new command and it's version info.
26 */
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
31 };
32
octep_pfvf_validate_version(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)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)
36 {
37 u32 vf_version = (u32)cmd.s_version.version;
38
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;
43 else
44 rsp->s_version.version = OCTEP_PFVF_MBOX_VERSION_CURRENT;
45
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);
49
50 rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
51 }
52
octep_pfvf_get_link_status(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)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)
56 {
57 int status;
58
59 status = octep_ctrl_net_get_link_status(oct, vf_id);
60 if (status < 0) {
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");
63 return;
64 }
65 rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
66 rsp->s_link_status.status = status;
67 }
68
octep_pfvf_set_link_status(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)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)
72 {
73 int err;
74
75 err = octep_ctrl_net_set_link_status(oct, vf_id, cmd.s_link_status.status, true);
76 if (err) {
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");
79 return;
80 }
81 rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
82 }
83
octep_pfvf_set_rx_state(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)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)
87 {
88 int err;
89
90 err = octep_ctrl_net_set_rx_state(oct, vf_id, cmd.s_link_state.state, true);
91 if (err) {
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");
94 return;
95 }
96 rsp->s_link_state.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
97 }
98
octep_send_notification(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd)99 static int octep_send_notification(struct octep_device *oct, u32 vf_id,
100 union octep_pfvf_mbox_word cmd)
101 {
102 u32 max_rings_per_vf, vf_mbox_queue;
103 struct octep_mbox *mbox;
104
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);
109 return -EOPNOTSUPP;
110 }
111
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);
116 return -EINVAL;
117 }
118 mbox = oct->mbox[vf_mbox_queue];
119
120 mutex_lock(&mbox->lock);
121 writeq(cmd.u64, mbox->pf_vf_data_reg);
122 mutex_unlock(&mbox->lock);
123
124 return 0;
125 }
126
octep_pfvf_set_mtu(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)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)
130 {
131 int err;
132
133 err = octep_ctrl_net_set_mtu(oct, vf_id, cmd.s_set_mtu.mtu, true);
134 if (err) {
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");
137 return;
138 }
139 rsp->s_set_mtu.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
140 }
141
octep_pfvf_get_mtu(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)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)
145 {
146 int max_rx_pktlen = oct->netdev->max_mtu + (ETH_HLEN + ETH_FCS_LEN);
147
148 rsp->s_set_mtu.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
149 rsp->s_get_mtu.mtu = max_rx_pktlen;
150 }
151
octep_pfvf_set_mac_addr(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)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)
155 {
156 int err;
157
158 err = octep_ctrl_net_set_mac_addr(oct, vf_id, cmd.s_set_mac.mac_addr, true);
159 if (err) {
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");
162 return;
163 }
164 rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
165 }
166
octep_pfvf_get_mac_addr(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)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)
170 {
171 int err;
172
173 err = octep_ctrl_net_get_mac_addr(oct, vf_id, rsp->s_set_mac.mac_addr);
174 if (err) {
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");
177 return;
178 }
179 rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
180 }
181
octep_pfvf_dev_remove(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)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)
185 {
186 int err;
187
188 err = octep_ctrl_net_dev_remove(oct, vf_id);
189 if (err) {
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",
192 vf_id);
193 return;
194 }
195 rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
196 }
197
octep_pfvf_get_fw_info(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)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)
201 {
202 struct octep_fw_info fw_info;
203 int err;
204
205 err = octep_ctrl_net_get_info(oct, vf_id, &fw_info);
206 if (err) {
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");
209 return;
210 }
211
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;
216
217 rsp->s_fw_info.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
218 }
219
octep_pfvf_set_offloads(struct octep_device * oct,u32 vf_id,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)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)
223 {
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
227 };
228 int err;
229
230 err = octep_ctrl_net_set_offloads(oct, vf_id, &offloads, true);
231 if (err) {
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");
234 return;
235 }
236 rsp->s_offloads.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
237 }
238
octep_setup_pfvf_mbox(struct octep_device * oct)239 int octep_setup_pfvf_mbox(struct octep_device *oct)
240 {
241 int i = 0, num_vfs = 0, rings_per_vf = 0;
242 int ring = 0;
243
244 num_vfs = oct->conf->sriov_cfg.active_vfs;
245 rings_per_vf = oct->conf->sriov_cfg.max_rings_per_vf;
246
247 for (i = 0; i < num_vfs; i++) {
248 ring = rings_per_vf * i;
249 oct->mbox[ring] = vzalloc(sizeof(*oct->mbox[ring]));
250
251 if (!oct->mbox[ring])
252 goto free_mbox;
253
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);
262 }
263 return 0;
264
265 free_mbox:
266 while (i) {
267 i--;
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;
273 }
274 return -ENOMEM;
275 }
276
octep_delete_pfvf_mbox(struct octep_device * oct)277 void octep_delete_pfvf_mbox(struct octep_device *oct)
278 {
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;
282
283 for (i = 0; i < num_vfs; i++) {
284 ring = vf_srn + rings_per_vf * i;
285 if (!oct->mbox[ring])
286 continue;
287
288 if (work_pending(&oct->mbox[ring]->wk.work))
289 cancel_work_sync(&oct->mbox[ring]->wk.work);
290
291 mutex_destroy(&oct->mbox[ring]->lock);
292 vfree(oct->mbox[ring]);
293 oct->mbox[ring] = NULL;
294 }
295 }
296
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)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)
301 {
302 int length = 0;
303 int i = 0;
304 int err;
305 struct octep_iface_link_info link_info;
306 struct octep_iface_rx_stats rx_stats;
307 struct octep_iface_tx_stats tx_stats;
308
309 rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
310
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
316 * the requested data
317 */
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);
322 if (!err) {
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));
326 } else {
327 rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
328 return;
329 }
330 break;
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);
335 if (!err) {
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,
340 sizeof(tx_stats));
341
342 } else {
343 rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
344 return;
345 }
346 break;
347 }
348 *((int32_t *)rsp->s_data.data) = mbox->message_len;
349 return;
350 }
351
352 if (mbox->message_len > OCTEP_PFVF_MBOX_MAX_DATA_SIZE)
353 length = OCTEP_PFVF_MBOX_MAX_DATA_SIZE;
354 else
355 length = mbox->message_len;
356
357 mbox->message_len -= length;
358
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++;
363 }
364 }
365
octep_pfvf_notify(struct octep_device * oct,struct octep_ctrl_mbox_msg * msg)366 void octep_pfvf_notify(struct octep_device *oct, struct octep_ctrl_mbox_msg *msg)
367 {
368 union octep_pfvf_mbox_word notif = { 0 };
369 struct octep_ctrl_net_f2h_req *req;
370
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;
376 break;
377 default:
378 pr_info("Unknown mbox notif for vf: %u\n",
379 req->hdr.s.cmd);
380 return;
381 }
382
383 notif.s.type = OCTEP_PFVF_MBOX_TYPE_CMD;
384 octep_send_notification(oct, msg->hdr.s.vf_idx, notif);
385 }
386
octep_pfvf_mbox_work(struct work_struct * work)387 void octep_pfvf_mbox_work(struct work_struct *work)
388 {
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;
394 int vf_id;
395
396 mbox = (struct octep_mbox *)wk->ctxptr;
397 oct = (struct octep_device *)mbox->oct;
398 vf_id = mbox->vf_id;
399
400 mutex_lock(&mbox->lock);
401 cmd.u64 = readq(mbox->vf_pf_data_reg);
402 rsp.u64 = 0;
403
404 switch (cmd.s.opcode) {
405 case OCTEP_PFVF_MBOX_CMD_VERSION:
406 octep_pfvf_validate_version(oct, vf_id, cmd, &rsp);
407 break;
408 case OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS:
409 octep_pfvf_get_link_status(oct, vf_id, cmd, &rsp);
410 break;
411 case OCTEP_PFVF_MBOX_CMD_SET_LINK_STATUS:
412 octep_pfvf_set_link_status(oct, vf_id, cmd, &rsp);
413 break;
414 case OCTEP_PFVF_MBOX_CMD_SET_RX_STATE:
415 octep_pfvf_set_rx_state(oct, vf_id, cmd, &rsp);
416 break;
417 case OCTEP_PFVF_MBOX_CMD_SET_MTU:
418 octep_pfvf_set_mtu(oct, vf_id, cmd, &rsp);
419 break;
420 case OCTEP_PFVF_MBOX_CMD_SET_MAC_ADDR:
421 octep_pfvf_set_mac_addr(oct, vf_id, cmd, &rsp);
422 break;
423 case OCTEP_PFVF_MBOX_CMD_GET_MAC_ADDR:
424 octep_pfvf_get_mac_addr(oct, vf_id, cmd, &rsp);
425 break;
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);
429 break;
430 case OCTEP_PFVF_MBOX_CMD_GET_MTU:
431 octep_pfvf_get_mtu(oct, vf_id, cmd, &rsp);
432 break;
433 case OCTEP_PFVF_MBOX_CMD_DEV_REMOVE:
434 octep_pfvf_dev_remove(oct, vf_id, cmd, &rsp);
435 break;
436 case OCTEP_PFVF_MBOX_CMD_GET_FW_INFO:
437 octep_pfvf_get_fw_info(oct, vf_id, cmd, &rsp);
438 break;
439 case OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS:
440 octep_pfvf_set_offloads(oct, vf_id, cmd, &rsp);
441 break;
442 default:
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;
445 break;
446 }
447 writeq(rsp.u64, mbox->vf_pf_data_reg);
448 mutex_unlock(&mbox->lock);
449 }
450