GNU Linux-libre 6.8.9-gnu
[releases.git] / drivers / net / ethernet / marvell / octeon_ep / octep_pfvf_mbox.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }