GNU Linux-libre 4.19.286-gnu1
[releases.git] / drivers / net / ethernet / netronome / nfp / flower / main.c
1 /*
2  * Copyright (C) 2017 Netronome Systems, Inc.
3  *
4  * This software is dual licensed under the GNU General License Version 2,
5  * June 1991 as shown in the file COPYING in the top-level directory of this
6  * source tree or the BSD 2-Clause License provided below.  You have the
7  * option to license this software under the complete terms of either license.
8  *
9  * The BSD 2-Clause License:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      1. Redistributions of source code must retain the above
16  *         copyright notice, this list of conditions and the following
17  *         disclaimer.
18  *
19  *      2. Redistributions in binary form must reproduce the above
20  *         copyright notice, this list of conditions and the following
21  *         disclaimer in the documentation and/or other materials
22  *         provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  */
33
34 #include <linux/etherdevice.h>
35 #include <linux/lockdep.h>
36 #include <linux/pci.h>
37 #include <linux/skbuff.h>
38 #include <linux/vmalloc.h>
39 #include <net/devlink.h>
40 #include <net/dst_metadata.h>
41
42 #include "main.h"
43 #include "../nfpcore/nfp_cpp.h"
44 #include "../nfpcore/nfp_nffw.h"
45 #include "../nfpcore/nfp_nsp.h"
46 #include "../nfp_app.h"
47 #include "../nfp_main.h"
48 #include "../nfp_net.h"
49 #include "../nfp_net_repr.h"
50 #include "../nfp_port.h"
51 #include "./cmsg.h"
52
53 #define NFP_FLOWER_ALLOWED_VER 0x0001000000010000UL
54
55 static const char *nfp_flower_extra_cap(struct nfp_app *app, struct nfp_net *nn)
56 {
57         return "FLOWER";
58 }
59
60 static enum devlink_eswitch_mode eswitch_mode_get(struct nfp_app *app)
61 {
62         return DEVLINK_ESWITCH_MODE_SWITCHDEV;
63 }
64
65 static enum nfp_repr_type
66 nfp_flower_repr_get_type_and_port(struct nfp_app *app, u32 port_id, u8 *port)
67 {
68         switch (FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE, port_id)) {
69         case NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT:
70                 *port = FIELD_GET(NFP_FLOWER_CMSG_PORT_PHYS_PORT_NUM,
71                                   port_id);
72                 return NFP_REPR_TYPE_PHYS_PORT;
73
74         case NFP_FLOWER_CMSG_PORT_TYPE_PCIE_PORT:
75                 *port = FIELD_GET(NFP_FLOWER_CMSG_PORT_VNIC, port_id);
76                 if (FIELD_GET(NFP_FLOWER_CMSG_PORT_VNIC_TYPE, port_id) ==
77                     NFP_FLOWER_CMSG_PORT_VNIC_TYPE_PF)
78                         return NFP_REPR_TYPE_PF;
79                 else
80                         return NFP_REPR_TYPE_VF;
81         }
82
83         return __NFP_REPR_TYPE_MAX;
84 }
85
86 static struct net_device *
87 nfp_flower_repr_get(struct nfp_app *app, u32 port_id)
88 {
89         enum nfp_repr_type repr_type;
90         struct nfp_reprs *reprs;
91         u8 port = 0;
92
93         repr_type = nfp_flower_repr_get_type_and_port(app, port_id, &port);
94         if (repr_type > NFP_REPR_TYPE_MAX)
95                 return NULL;
96
97         reprs = rcu_dereference(app->reprs[repr_type]);
98         if (!reprs)
99                 return NULL;
100
101         if (port >= reprs->num_reprs)
102                 return NULL;
103
104         return rcu_dereference(reprs->reprs[port]);
105 }
106
107 static int
108 nfp_flower_reprs_reify(struct nfp_app *app, enum nfp_repr_type type,
109                        bool exists)
110 {
111         struct nfp_reprs *reprs;
112         int i, err, count = 0;
113
114         reprs = rcu_dereference_protected(app->reprs[type],
115                                           lockdep_is_held(&app->pf->lock));
116         if (!reprs)
117                 return 0;
118
119         for (i = 0; i < reprs->num_reprs; i++) {
120                 struct net_device *netdev;
121
122                 netdev = nfp_repr_get_locked(app, reprs, i);
123                 if (netdev) {
124                         struct nfp_repr *repr = netdev_priv(netdev);
125
126                         err = nfp_flower_cmsg_portreify(repr, exists);
127                         if (err)
128                                 return err;
129                         count++;
130                 }
131         }
132
133         return count;
134 }
135
136 static int
137 nfp_flower_wait_repr_reify(struct nfp_app *app, atomic_t *replies, int tot_repl)
138 {
139         struct nfp_flower_priv *priv = app->priv;
140         int err;
141
142         if (!tot_repl)
143                 return 0;
144
145         lockdep_assert_held(&app->pf->lock);
146         err = wait_event_interruptible_timeout(priv->reify_wait_queue,
147                                                atomic_read(replies) >= tot_repl,
148                                                msecs_to_jiffies(10));
149         if (err <= 0) {
150                 nfp_warn(app->cpp, "Not all reprs responded to reify\n");
151                 return -EIO;
152         }
153
154         return 0;
155 }
156
157 static int
158 nfp_flower_repr_netdev_open(struct nfp_app *app, struct nfp_repr *repr)
159 {
160         int err;
161
162         err = nfp_flower_cmsg_portmod(repr, true, repr->netdev->mtu, false);
163         if (err)
164                 return err;
165
166         netif_tx_wake_all_queues(repr->netdev);
167
168         return 0;
169 }
170
171 static int
172 nfp_flower_repr_netdev_stop(struct nfp_app *app, struct nfp_repr *repr)
173 {
174         netif_tx_disable(repr->netdev);
175
176         return nfp_flower_cmsg_portmod(repr, false, repr->netdev->mtu, false);
177 }
178
179 static int
180 nfp_flower_repr_netdev_init(struct nfp_app *app, struct net_device *netdev)
181 {
182         return tc_setup_cb_egdev_register(netdev,
183                                           nfp_flower_setup_tc_egress_cb,
184                                           netdev_priv(netdev));
185 }
186
187 static void
188 nfp_flower_repr_netdev_clean(struct nfp_app *app, struct net_device *netdev)
189 {
190         struct nfp_repr *repr = netdev_priv(netdev);
191
192         kfree(repr->app_priv);
193
194         tc_setup_cb_egdev_unregister(netdev, nfp_flower_setup_tc_egress_cb,
195                                      netdev_priv(netdev));
196 }
197
198 static void
199 nfp_flower_repr_netdev_preclean(struct nfp_app *app, struct net_device *netdev)
200 {
201         struct nfp_repr *repr = netdev_priv(netdev);
202         struct nfp_flower_priv *priv = app->priv;
203         atomic_t *replies = &priv->reify_replies;
204         int err;
205
206         atomic_set(replies, 0);
207         err = nfp_flower_cmsg_portreify(repr, false);
208         if (err) {
209                 nfp_warn(app->cpp, "Failed to notify firmware about repr destruction\n");
210                 return;
211         }
212
213         nfp_flower_wait_repr_reify(app, replies, 1);
214 }
215
216 static void nfp_flower_sriov_disable(struct nfp_app *app)
217 {
218         struct nfp_flower_priv *priv = app->priv;
219
220         if (!priv->nn)
221                 return;
222
223         nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_VF);
224 }
225
226 static int
227 nfp_flower_spawn_vnic_reprs(struct nfp_app *app,
228                             enum nfp_flower_cmsg_port_vnic_type vnic_type,
229                             enum nfp_repr_type repr_type, unsigned int cnt)
230 {
231         u8 nfp_pcie = nfp_cppcore_pcie_unit(app->pf->cpp);
232         struct nfp_flower_priv *priv = app->priv;
233         atomic_t *replies = &priv->reify_replies;
234         struct nfp_flower_repr_priv *repr_priv;
235         enum nfp_port_type port_type;
236         struct nfp_repr *nfp_repr;
237         struct nfp_reprs *reprs;
238         int i, err, reify_cnt;
239         const u8 queue = 0;
240
241         port_type = repr_type == NFP_REPR_TYPE_PF ? NFP_PORT_PF_PORT :
242                                                     NFP_PORT_VF_PORT;
243
244         reprs = nfp_reprs_alloc(cnt);
245         if (!reprs)
246                 return -ENOMEM;
247
248         for (i = 0; i < cnt; i++) {
249                 struct net_device *repr;
250                 struct nfp_port *port;
251                 u32 port_id;
252
253                 repr = nfp_repr_alloc(app);
254                 if (!repr) {
255                         err = -ENOMEM;
256                         goto err_reprs_clean;
257                 }
258
259                 repr_priv = kzalloc(sizeof(*repr_priv), GFP_KERNEL);
260                 if (!repr_priv) {
261                         err = -ENOMEM;
262                         nfp_repr_free(repr);
263                         goto err_reprs_clean;
264                 }
265
266                 nfp_repr = netdev_priv(repr);
267                 nfp_repr->app_priv = repr_priv;
268
269                 /* For now we only support 1 PF */
270                 WARN_ON(repr_type == NFP_REPR_TYPE_PF && i);
271
272                 port = nfp_port_alloc(app, port_type, repr);
273                 if (IS_ERR(port)) {
274                         err = PTR_ERR(port);
275                         kfree(repr_priv);
276                         nfp_repr_free(repr);
277                         goto err_reprs_clean;
278                 }
279                 if (repr_type == NFP_REPR_TYPE_PF) {
280                         port->pf_id = i;
281                         port->vnic = priv->nn->dp.ctrl_bar;
282                 } else {
283                         port->pf_id = 0;
284                         port->vf_id = i;
285                         port->vnic =
286                                 app->pf->vf_cfg_mem + i * NFP_NET_CFG_BAR_SZ;
287                 }
288
289                 eth_hw_addr_random(repr);
290
291                 port_id = nfp_flower_cmsg_pcie_port(nfp_pcie, vnic_type,
292                                                     i, queue);
293                 err = nfp_repr_init(app, repr,
294                                     port_id, port, priv->nn->dp.netdev);
295                 if (err) {
296                         kfree(repr_priv);
297                         nfp_port_free(port);
298                         nfp_repr_free(repr);
299                         goto err_reprs_clean;
300                 }
301
302                 RCU_INIT_POINTER(reprs->reprs[i], repr);
303                 nfp_info(app->cpp, "%s%d Representor(%s) created\n",
304                          repr_type == NFP_REPR_TYPE_PF ? "PF" : "VF", i,
305                          repr->name);
306         }
307
308         nfp_app_reprs_set(app, repr_type, reprs);
309
310         atomic_set(replies, 0);
311         reify_cnt = nfp_flower_reprs_reify(app, repr_type, true);
312         if (reify_cnt < 0) {
313                 err = reify_cnt;
314                 nfp_warn(app->cpp, "Failed to notify firmware about repr creation\n");
315                 goto err_reprs_remove;
316         }
317
318         err = nfp_flower_wait_repr_reify(app, replies, reify_cnt);
319         if (err)
320                 goto err_reprs_remove;
321
322         return 0;
323 err_reprs_remove:
324         reprs = nfp_app_reprs_set(app, repr_type, NULL);
325 err_reprs_clean:
326         nfp_reprs_clean_and_free(app, reprs);
327         return err;
328 }
329
330 static int nfp_flower_sriov_enable(struct nfp_app *app, int num_vfs)
331 {
332         struct nfp_flower_priv *priv = app->priv;
333
334         if (!priv->nn)
335                 return 0;
336
337         return nfp_flower_spawn_vnic_reprs(app,
338                                            NFP_FLOWER_CMSG_PORT_VNIC_TYPE_VF,
339                                            NFP_REPR_TYPE_VF, num_vfs);
340 }
341
342 static int
343 nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv)
344 {
345         struct nfp_eth_table *eth_tbl = app->pf->eth_tbl;
346         atomic_t *replies = &priv->reify_replies;
347         struct nfp_flower_repr_priv *repr_priv;
348         struct nfp_repr *nfp_repr;
349         struct sk_buff *ctrl_skb;
350         struct nfp_reprs *reprs;
351         int err, reify_cnt;
352         unsigned int i;
353
354         ctrl_skb = nfp_flower_cmsg_mac_repr_start(app, eth_tbl->count);
355         if (!ctrl_skb)
356                 return -ENOMEM;
357
358         reprs = nfp_reprs_alloc(eth_tbl->max_index + 1);
359         if (!reprs) {
360                 err = -ENOMEM;
361                 goto err_free_ctrl_skb;
362         }
363
364         for (i = 0; i < eth_tbl->count; i++) {
365                 unsigned int phys_port = eth_tbl->ports[i].index;
366                 struct net_device *repr;
367                 struct nfp_port *port;
368                 u32 cmsg_port_id;
369
370                 repr = nfp_repr_alloc(app);
371                 if (!repr) {
372                         err = -ENOMEM;
373                         goto err_reprs_clean;
374                 }
375
376                 repr_priv = kzalloc(sizeof(*repr_priv), GFP_KERNEL);
377                 if (!repr_priv) {
378                         err = -ENOMEM;
379                         nfp_repr_free(repr);
380                         goto err_reprs_clean;
381                 }
382
383                 nfp_repr = netdev_priv(repr);
384                 nfp_repr->app_priv = repr_priv;
385
386                 port = nfp_port_alloc(app, NFP_PORT_PHYS_PORT, repr);
387                 if (IS_ERR(port)) {
388                         err = PTR_ERR(port);
389                         kfree(repr_priv);
390                         nfp_repr_free(repr);
391                         goto err_reprs_clean;
392                 }
393                 err = nfp_port_init_phy_port(app->pf, app, port, i);
394                 if (err) {
395                         kfree(repr_priv);
396                         nfp_port_free(port);
397                         nfp_repr_free(repr);
398                         goto err_reprs_clean;
399                 }
400
401                 SET_NETDEV_DEV(repr, &priv->nn->pdev->dev);
402                 nfp_net_get_mac_addr(app->pf, repr, port);
403
404                 cmsg_port_id = nfp_flower_cmsg_phys_port(phys_port);
405                 err = nfp_repr_init(app, repr,
406                                     cmsg_port_id, port, priv->nn->dp.netdev);
407                 if (err) {
408                         kfree(repr_priv);
409                         nfp_port_free(port);
410                         nfp_repr_free(repr);
411                         goto err_reprs_clean;
412                 }
413
414                 nfp_flower_cmsg_mac_repr_add(ctrl_skb, i,
415                                              eth_tbl->ports[i].nbi,
416                                              eth_tbl->ports[i].base,
417                                              phys_port);
418
419                 RCU_INIT_POINTER(reprs->reprs[phys_port], repr);
420                 nfp_info(app->cpp, "Phys Port %d Representor(%s) created\n",
421                          phys_port, repr->name);
422         }
423
424         nfp_app_reprs_set(app, NFP_REPR_TYPE_PHYS_PORT, reprs);
425
426         /* The REIFY/MAC_REPR control messages should be sent after the MAC
427          * representors are registered using nfp_app_reprs_set().  This is
428          * because the firmware may respond with control messages for the
429          * MAC representors, f.e. to provide the driver with information
430          * about their state, and without registration the driver will drop
431          * any such messages.
432          */
433         atomic_set(replies, 0);
434         reify_cnt = nfp_flower_reprs_reify(app, NFP_REPR_TYPE_PHYS_PORT, true);
435         if (reify_cnt < 0) {
436                 err = reify_cnt;
437                 nfp_warn(app->cpp, "Failed to notify firmware about repr creation\n");
438                 goto err_reprs_remove;
439         }
440
441         err = nfp_flower_wait_repr_reify(app, replies, reify_cnt);
442         if (err)
443                 goto err_reprs_remove;
444
445         nfp_ctrl_tx(app->ctrl, ctrl_skb);
446
447         return 0;
448 err_reprs_remove:
449         reprs = nfp_app_reprs_set(app, NFP_REPR_TYPE_PHYS_PORT, NULL);
450 err_reprs_clean:
451         nfp_reprs_clean_and_free(app, reprs);
452 err_free_ctrl_skb:
453         kfree_skb(ctrl_skb);
454         return err;
455 }
456
457 static int nfp_flower_vnic_alloc(struct nfp_app *app, struct nfp_net *nn,
458                                  unsigned int id)
459 {
460         if (id > 0) {
461                 nfp_warn(app->cpp, "FlowerNIC doesn't support more than one data vNIC\n");
462                 goto err_invalid_port;
463         }
464
465         eth_hw_addr_random(nn->dp.netdev);
466         netif_keep_dst(nn->dp.netdev);
467         nn->vnic_no_name = true;
468
469         return 0;
470
471 err_invalid_port:
472         nn->port = nfp_port_alloc(app, NFP_PORT_INVALID, nn->dp.netdev);
473         return PTR_ERR_OR_ZERO(nn->port);
474 }
475
476 static void nfp_flower_vnic_clean(struct nfp_app *app, struct nfp_net *nn)
477 {
478         struct nfp_flower_priv *priv = app->priv;
479
480         if (app->pf->num_vfs)
481                 nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_VF);
482         nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PF);
483         nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PHYS_PORT);
484
485         priv->nn = NULL;
486 }
487
488 static int nfp_flower_vnic_init(struct nfp_app *app, struct nfp_net *nn)
489 {
490         struct nfp_flower_priv *priv = app->priv;
491         int err;
492
493         priv->nn = nn;
494
495         err = nfp_flower_spawn_phy_reprs(app, app->priv);
496         if (err)
497                 goto err_clear_nn;
498
499         err = nfp_flower_spawn_vnic_reprs(app,
500                                           NFP_FLOWER_CMSG_PORT_VNIC_TYPE_PF,
501                                           NFP_REPR_TYPE_PF, 1);
502         if (err)
503                 goto err_destroy_reprs_phy;
504
505         if (app->pf->num_vfs) {
506                 err = nfp_flower_spawn_vnic_reprs(app,
507                                                   NFP_FLOWER_CMSG_PORT_VNIC_TYPE_VF,
508                                                   NFP_REPR_TYPE_VF,
509                                                   app->pf->num_vfs);
510                 if (err)
511                         goto err_destroy_reprs_pf;
512         }
513
514         return 0;
515
516 err_destroy_reprs_pf:
517         nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PF);
518 err_destroy_reprs_phy:
519         nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PHYS_PORT);
520 err_clear_nn:
521         priv->nn = NULL;
522         return err;
523 }
524
525 static int nfp_flower_init(struct nfp_app *app)
526 {
527         const struct nfp_pf *pf = app->pf;
528         struct nfp_flower_priv *app_priv;
529         u64 version, features;
530         int err;
531
532         if (!pf->eth_tbl) {
533                 nfp_warn(app->cpp, "FlowerNIC requires eth table\n");
534                 return -EINVAL;
535         }
536
537         if (!pf->mac_stats_bar) {
538                 nfp_warn(app->cpp, "FlowerNIC requires mac_stats BAR\n");
539                 return -EINVAL;
540         }
541
542         if (!pf->vf_cfg_bar) {
543                 nfp_warn(app->cpp, "FlowerNIC requires vf_cfg BAR\n");
544                 return -EINVAL;
545         }
546
547         version = nfp_rtsym_read_le(app->pf->rtbl, "hw_flower_version", &err);
548         if (err) {
549                 nfp_warn(app->cpp, "FlowerNIC requires hw_flower_version memory symbol\n");
550                 return err;
551         }
552
553         /* We need to ensure hardware has enough flower capabilities. */
554         if (version != NFP_FLOWER_ALLOWED_VER) {
555                 nfp_warn(app->cpp, "FlowerNIC: unsupported firmware version\n");
556                 return -EINVAL;
557         }
558
559         app_priv = vzalloc(sizeof(struct nfp_flower_priv));
560         if (!app_priv)
561                 return -ENOMEM;
562
563         app->priv = app_priv;
564         app_priv->app = app;
565         skb_queue_head_init(&app_priv->cmsg_skbs_high);
566         skb_queue_head_init(&app_priv->cmsg_skbs_low);
567         INIT_WORK(&app_priv->cmsg_work, nfp_flower_cmsg_process_rx);
568         init_waitqueue_head(&app_priv->reify_wait_queue);
569
570         init_waitqueue_head(&app_priv->mtu_conf.wait_q);
571         spin_lock_init(&app_priv->mtu_conf.lock);
572
573         err = nfp_flower_metadata_init(app);
574         if (err)
575                 goto err_free_app_priv;
576
577         /* Extract the extra features supported by the firmware. */
578         features = nfp_rtsym_read_le(app->pf->rtbl,
579                                      "_abi_flower_extra_features", &err);
580         if (err)
581                 app_priv->flower_ext_feats = 0;
582         else
583                 app_priv->flower_ext_feats = features;
584
585         /* Tell the firmware that the driver supports lag. */
586         err = nfp_rtsym_write_le(app->pf->rtbl,
587                                  "_abi_flower_balance_sync_enable", 1);
588         if (!err) {
589                 app_priv->flower_ext_feats |= NFP_FL_FEATS_LAG;
590                 nfp_flower_lag_init(&app_priv->nfp_lag);
591         } else if (err == -ENOENT) {
592                 nfp_warn(app->cpp, "LAG not supported by FW.\n");
593         } else {
594                 goto err_cleanup_metadata;
595         }
596
597         return 0;
598
599 err_cleanup_metadata:
600         nfp_flower_metadata_cleanup(app);
601 err_free_app_priv:
602         vfree(app->priv);
603         return err;
604 }
605
606 static void nfp_flower_clean(struct nfp_app *app)
607 {
608         struct nfp_flower_priv *app_priv = app->priv;
609
610         skb_queue_purge(&app_priv->cmsg_skbs_high);
611         skb_queue_purge(&app_priv->cmsg_skbs_low);
612         flush_work(&app_priv->cmsg_work);
613
614         if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG)
615                 nfp_flower_lag_cleanup(&app_priv->nfp_lag);
616
617         nfp_flower_metadata_cleanup(app);
618         vfree(app->priv);
619         app->priv = NULL;
620 }
621
622 static bool nfp_flower_check_ack(struct nfp_flower_priv *app_priv)
623 {
624         bool ret;
625
626         spin_lock_bh(&app_priv->mtu_conf.lock);
627         ret = app_priv->mtu_conf.ack;
628         spin_unlock_bh(&app_priv->mtu_conf.lock);
629
630         return ret;
631 }
632
633 static int
634 nfp_flower_repr_change_mtu(struct nfp_app *app, struct net_device *netdev,
635                            int new_mtu)
636 {
637         struct nfp_flower_priv *app_priv = app->priv;
638         struct nfp_repr *repr = netdev_priv(netdev);
639         int err, ack;
640
641         /* Only need to config FW for physical port MTU change. */
642         if (repr->port->type != NFP_PORT_PHYS_PORT)
643                 return 0;
644
645         if (!(app_priv->flower_ext_feats & NFP_FL_NBI_MTU_SETTING)) {
646                 nfp_err(app->cpp, "Physical port MTU setting not supported\n");
647                 return -EINVAL;
648         }
649
650         spin_lock_bh(&app_priv->mtu_conf.lock);
651         app_priv->mtu_conf.ack = false;
652         app_priv->mtu_conf.requested_val = new_mtu;
653         app_priv->mtu_conf.portnum = repr->dst->u.port_info.port_id;
654         spin_unlock_bh(&app_priv->mtu_conf.lock);
655
656         err = nfp_flower_cmsg_portmod(repr, netif_carrier_ok(netdev), new_mtu,
657                                       true);
658         if (err) {
659                 spin_lock_bh(&app_priv->mtu_conf.lock);
660                 app_priv->mtu_conf.requested_val = 0;
661                 spin_unlock_bh(&app_priv->mtu_conf.lock);
662                 return err;
663         }
664
665         /* Wait for fw to ack the change. */
666         ack = wait_event_timeout(app_priv->mtu_conf.wait_q,
667                                  nfp_flower_check_ack(app_priv),
668                                  msecs_to_jiffies(10));
669
670         if (!ack) {
671                 spin_lock_bh(&app_priv->mtu_conf.lock);
672                 app_priv->mtu_conf.requested_val = 0;
673                 spin_unlock_bh(&app_priv->mtu_conf.lock);
674                 nfp_warn(app->cpp, "MTU change not verified with fw\n");
675                 return -EIO;
676         }
677
678         return 0;
679 }
680
681 static int nfp_flower_start(struct nfp_app *app)
682 {
683         struct nfp_flower_priv *app_priv = app->priv;
684         int err;
685
686         if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG) {
687                 err = nfp_flower_lag_reset(&app_priv->nfp_lag);
688                 if (err)
689                         return err;
690
691                 err = register_netdevice_notifier(&app_priv->nfp_lag.lag_nb);
692                 if (err)
693                         return err;
694         }
695
696         return nfp_tunnel_config_start(app);
697 }
698
699 static void nfp_flower_stop(struct nfp_app *app)
700 {
701         struct nfp_flower_priv *app_priv = app->priv;
702
703         if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG)
704                 unregister_netdevice_notifier(&app_priv->nfp_lag.lag_nb);
705
706         nfp_tunnel_config_stop(app);
707 }
708
709 const struct nfp_app_type app_flower = {
710         .id             = NFP_APP_FLOWER_NIC,
711         .name           = "flower",
712
713         .ctrl_cap_mask  = ~0U,
714         .ctrl_has_meta  = true,
715
716         .extra_cap      = nfp_flower_extra_cap,
717
718         .init           = nfp_flower_init,
719         .clean          = nfp_flower_clean,
720
721         .repr_change_mtu  = nfp_flower_repr_change_mtu,
722
723         .vnic_alloc     = nfp_flower_vnic_alloc,
724         .vnic_init      = nfp_flower_vnic_init,
725         .vnic_clean     = nfp_flower_vnic_clean,
726
727         .repr_init      = nfp_flower_repr_netdev_init,
728         .repr_preclean  = nfp_flower_repr_netdev_preclean,
729         .repr_clean     = nfp_flower_repr_netdev_clean,
730
731         .repr_open      = nfp_flower_repr_netdev_open,
732         .repr_stop      = nfp_flower_repr_netdev_stop,
733
734         .start          = nfp_flower_start,
735         .stop           = nfp_flower_stop,
736
737         .ctrl_msg_rx    = nfp_flower_cmsg_rx,
738
739         .sriov_enable   = nfp_flower_sriov_enable,
740         .sriov_disable  = nfp_flower_sriov_disable,
741
742         .eswitch_mode_get  = eswitch_mode_get,
743         .repr_get       = nfp_flower_repr_get,
744
745         .setup_tc       = nfp_flower_setup_tc,
746 };