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 goto err_reprs_clean; 263 } 264 265 nfp_repr = netdev_priv(repr); 266 nfp_repr->app_priv = repr_priv; 267 268 /* For now we only support 1 PF */ 269 WARN_ON(repr_type == NFP_REPR_TYPE_PF && i); 270 271 port = nfp_port_alloc(app, port_type, repr); 272 if (IS_ERR(port)) { 273 err = PTR_ERR(port); 274 nfp_repr_free(repr); 275 goto err_reprs_clean; 276 } 277 if (repr_type == NFP_REPR_TYPE_PF) { 278 port->pf_id = i; 279 port->vnic = priv->nn->dp.ctrl_bar; 280 } else { 281 port->pf_id = 0; 282 port->vf_id = i; 283 port->vnic = 284 app->pf->vf_cfg_mem + i * NFP_NET_CFG_BAR_SZ; 285 } 286 287 eth_hw_addr_random(repr); 288 289 port_id = nfp_flower_cmsg_pcie_port(nfp_pcie, vnic_type, 290 i, queue); 291 err = nfp_repr_init(app, repr, 292 port_id, port, priv->nn->dp.netdev); 293 if (err) { 294 nfp_port_free(port); 295 nfp_repr_free(repr); 296 goto err_reprs_clean; 297 } 298 299 RCU_INIT_POINTER(reprs->reprs[i], repr); 300 nfp_info(app->cpp, "%s%d Representor(%s) created\n", 301 repr_type == NFP_REPR_TYPE_PF ? "PF" : "VF", i, 302 repr->name); 303 } 304 305 nfp_app_reprs_set(app, repr_type, reprs); 306 307 atomic_set(replies, 0); 308 reify_cnt = nfp_flower_reprs_reify(app, repr_type, true); 309 if (reify_cnt < 0) { 310 err = reify_cnt; 311 nfp_warn(app->cpp, "Failed to notify firmware about repr creation\n"); 312 goto err_reprs_remove; 313 } 314 315 err = nfp_flower_wait_repr_reify(app, replies, reify_cnt); 316 if (err) 317 goto err_reprs_remove; 318 319 return 0; 320 err_reprs_remove: 321 reprs = nfp_app_reprs_set(app, repr_type, NULL); 322 err_reprs_clean: 323 nfp_reprs_clean_and_free(app, reprs); 324 return err; 325 } 326 327 static int nfp_flower_sriov_enable(struct nfp_app *app, int num_vfs) 328 { 329 struct nfp_flower_priv *priv = app->priv; 330 331 if (!priv->nn) 332 return 0; 333 334 return nfp_flower_spawn_vnic_reprs(app, 335 NFP_FLOWER_CMSG_PORT_VNIC_TYPE_VF, 336 NFP_REPR_TYPE_VF, num_vfs); 337 } 338 339 static int 340 nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv) 341 { 342 struct nfp_eth_table *eth_tbl = app->pf->eth_tbl; 343 atomic_t *replies = &priv->reify_replies; 344 struct nfp_flower_repr_priv *repr_priv; 345 struct nfp_repr *nfp_repr; 346 struct sk_buff *ctrl_skb; 347 struct nfp_reprs *reprs; 348 int err, reify_cnt; 349 unsigned int i; 350 351 ctrl_skb = nfp_flower_cmsg_mac_repr_start(app, eth_tbl->count); 352 if (!ctrl_skb) 353 return -ENOMEM; 354 355 reprs = nfp_reprs_alloc(eth_tbl->max_index + 1); 356 if (!reprs) { 357 err = -ENOMEM; 358 goto err_free_ctrl_skb; 359 } 360 361 for (i = 0; i < eth_tbl->count; i++) { 362 unsigned int phys_port = eth_tbl->ports[i].index; 363 struct net_device *repr; 364 struct nfp_port *port; 365 u32 cmsg_port_id; 366 367 repr = nfp_repr_alloc(app); 368 if (!repr) { 369 err = -ENOMEM; 370 goto err_reprs_clean; 371 } 372 373 repr_priv = kzalloc(sizeof(*repr_priv), GFP_KERNEL); 374 if (!repr_priv) { 375 err = -ENOMEM; 376 goto err_reprs_clean; 377 } 378 379 nfp_repr = netdev_priv(repr); 380 nfp_repr->app_priv = repr_priv; 381 382 port = nfp_port_alloc(app, NFP_PORT_PHYS_PORT, repr); 383 if (IS_ERR(port)) { 384 err = PTR_ERR(port); 385 nfp_repr_free(repr); 386 goto err_reprs_clean; 387 } 388 err = nfp_port_init_phy_port(app->pf, app, port, i); 389 if (err) { 390 nfp_port_free(port); 391 nfp_repr_free(repr); 392 goto err_reprs_clean; 393 } 394 395 SET_NETDEV_DEV(repr, &priv->nn->pdev->dev); 396 nfp_net_get_mac_addr(app->pf, repr, port); 397 398 cmsg_port_id = nfp_flower_cmsg_phys_port(phys_port); 399 err = nfp_repr_init(app, repr, 400 cmsg_port_id, port, priv->nn->dp.netdev); 401 if (err) { 402 nfp_port_free(port); 403 nfp_repr_free(repr); 404 goto err_reprs_clean; 405 } 406 407 nfp_flower_cmsg_mac_repr_add(ctrl_skb, i, 408 eth_tbl->ports[i].nbi, 409 eth_tbl->ports[i].base, 410 phys_port); 411 412 RCU_INIT_POINTER(reprs->reprs[phys_port], repr); 413 nfp_info(app->cpp, "Phys Port %d Representor(%s) created\n", 414 phys_port, repr->name); 415 } 416 417 nfp_app_reprs_set(app, NFP_REPR_TYPE_PHYS_PORT, reprs); 418 419 /* The REIFY/MAC_REPR control messages should be sent after the MAC 420 * representors are registered using nfp_app_reprs_set(). This is 421 * because the firmware may respond with control messages for the 422 * MAC representors, f.e. to provide the driver with information 423 * about their state, and without registration the driver will drop 424 * any such messages. 425 */ 426 atomic_set(replies, 0); 427 reify_cnt = nfp_flower_reprs_reify(app, NFP_REPR_TYPE_PHYS_PORT, true); 428 if (reify_cnt < 0) { 429 err = reify_cnt; 430 nfp_warn(app->cpp, "Failed to notify firmware about repr creation\n"); 431 goto err_reprs_remove; 432 } 433 434 err = nfp_flower_wait_repr_reify(app, replies, reify_cnt); 435 if (err) 436 goto err_reprs_remove; 437 438 nfp_ctrl_tx(app->ctrl, ctrl_skb); 439 440 return 0; 441 err_reprs_remove: 442 reprs = nfp_app_reprs_set(app, NFP_REPR_TYPE_PHYS_PORT, NULL); 443 err_reprs_clean: 444 nfp_reprs_clean_and_free(app, reprs); 445 err_free_ctrl_skb: 446 kfree_skb(ctrl_skb); 447 return err; 448 } 449 450 static int nfp_flower_vnic_alloc(struct nfp_app *app, struct nfp_net *nn, 451 unsigned int id) 452 { 453 if (id > 0) { 454 nfp_warn(app->cpp, "FlowerNIC doesn't support more than one data vNIC\n"); 455 goto err_invalid_port; 456 } 457 458 eth_hw_addr_random(nn->dp.netdev); 459 netif_keep_dst(nn->dp.netdev); 460 nn->vnic_no_name = true; 461 462 return 0; 463 464 err_invalid_port: 465 nn->port = nfp_port_alloc(app, NFP_PORT_INVALID, nn->dp.netdev); 466 return PTR_ERR_OR_ZERO(nn->port); 467 } 468 469 static void nfp_flower_vnic_clean(struct nfp_app *app, struct nfp_net *nn) 470 { 471 struct nfp_flower_priv *priv = app->priv; 472 473 if (app->pf->num_vfs) 474 nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_VF); 475 nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PF); 476 nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PHYS_PORT); 477 478 priv->nn = NULL; 479 } 480 481 static int nfp_flower_vnic_init(struct nfp_app *app, struct nfp_net *nn) 482 { 483 struct nfp_flower_priv *priv = app->priv; 484 int err; 485 486 priv->nn = nn; 487 488 err = nfp_flower_spawn_phy_reprs(app, app->priv); 489 if (err) 490 goto err_clear_nn; 491 492 err = nfp_flower_spawn_vnic_reprs(app, 493 NFP_FLOWER_CMSG_PORT_VNIC_TYPE_PF, 494 NFP_REPR_TYPE_PF, 1); 495 if (err) 496 goto err_destroy_reprs_phy; 497 498 if (app->pf->num_vfs) { 499 err = nfp_flower_spawn_vnic_reprs(app, 500 NFP_FLOWER_CMSG_PORT_VNIC_TYPE_VF, 501 NFP_REPR_TYPE_VF, 502 app->pf->num_vfs); 503 if (err) 504 goto err_destroy_reprs_pf; 505 } 506 507 return 0; 508 509 err_destroy_reprs_pf: 510 nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PF); 511 err_destroy_reprs_phy: 512 nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PHYS_PORT); 513 err_clear_nn: 514 priv->nn = NULL; 515 return err; 516 } 517 518 static int nfp_flower_init(struct nfp_app *app) 519 { 520 const struct nfp_pf *pf = app->pf; 521 struct nfp_flower_priv *app_priv; 522 u64 version, features; 523 int err; 524 525 if (!pf->eth_tbl) { 526 nfp_warn(app->cpp, "FlowerNIC requires eth table\n"); 527 return -EINVAL; 528 } 529 530 if (!pf->mac_stats_bar) { 531 nfp_warn(app->cpp, "FlowerNIC requires mac_stats BAR\n"); 532 return -EINVAL; 533 } 534 535 if (!pf->vf_cfg_bar) { 536 nfp_warn(app->cpp, "FlowerNIC requires vf_cfg BAR\n"); 537 return -EINVAL; 538 } 539 540 version = nfp_rtsym_read_le(app->pf->rtbl, "hw_flower_version", &err); 541 if (err) { 542 nfp_warn(app->cpp, "FlowerNIC requires hw_flower_version memory symbol\n"); 543 return err; 544 } 545 546 /* We need to ensure hardware has enough flower capabilities. */ 547 if (version != NFP_FLOWER_ALLOWED_VER) { 548 nfp_warn(app->cpp, "FlowerNIC: unsupported firmware version\n"); 549 return -EINVAL; 550 } 551 552 app_priv = vzalloc(sizeof(struct nfp_flower_priv)); 553 if (!app_priv) 554 return -ENOMEM; 555 556 app->priv = app_priv; 557 app_priv->app = app; 558 skb_queue_head_init(&app_priv->cmsg_skbs_high); 559 skb_queue_head_init(&app_priv->cmsg_skbs_low); 560 INIT_WORK(&app_priv->cmsg_work, nfp_flower_cmsg_process_rx); 561 init_waitqueue_head(&app_priv->reify_wait_queue); 562 563 init_waitqueue_head(&app_priv->mtu_conf.wait_q); 564 spin_lock_init(&app_priv->mtu_conf.lock); 565 566 err = nfp_flower_metadata_init(app); 567 if (err) 568 goto err_free_app_priv; 569 570 /* Extract the extra features supported by the firmware. */ 571 features = nfp_rtsym_read_le(app->pf->rtbl, 572 "_abi_flower_extra_features", &err); 573 if (err) 574 app_priv->flower_ext_feats = 0; 575 else 576 app_priv->flower_ext_feats = features; 577 578 /* Tell the firmware that the driver supports lag. */ 579 err = nfp_rtsym_write_le(app->pf->rtbl, 580 "_abi_flower_balance_sync_enable", 1); 581 if (!err) { 582 app_priv->flower_ext_feats |= NFP_FL_FEATS_LAG; 583 nfp_flower_lag_init(&app_priv->nfp_lag); 584 } else if (err == -ENOENT) { 585 nfp_warn(app->cpp, "LAG not supported by FW.\n"); 586 } else { 587 goto err_cleanup_metadata; 588 } 589 590 return 0; 591 592 err_cleanup_metadata: 593 nfp_flower_metadata_cleanup(app); 594 err_free_app_priv: 595 vfree(app->priv); 596 return err; 597 } 598 599 static void nfp_flower_clean(struct nfp_app *app) 600 { 601 struct nfp_flower_priv *app_priv = app->priv; 602 603 skb_queue_purge(&app_priv->cmsg_skbs_high); 604 skb_queue_purge(&app_priv->cmsg_skbs_low); 605 flush_work(&app_priv->cmsg_work); 606 607 if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG) 608 nfp_flower_lag_cleanup(&app_priv->nfp_lag); 609 610 nfp_flower_metadata_cleanup(app); 611 vfree(app->priv); 612 app->priv = NULL; 613 } 614 615 static bool nfp_flower_check_ack(struct nfp_flower_priv *app_priv) 616 { 617 bool ret; 618 619 spin_lock_bh(&app_priv->mtu_conf.lock); 620 ret = app_priv->mtu_conf.ack; 621 spin_unlock_bh(&app_priv->mtu_conf.lock); 622 623 return ret; 624 } 625 626 static int 627 nfp_flower_repr_change_mtu(struct nfp_app *app, struct net_device *netdev, 628 int new_mtu) 629 { 630 struct nfp_flower_priv *app_priv = app->priv; 631 struct nfp_repr *repr = netdev_priv(netdev); 632 int err, ack; 633 634 /* Only need to config FW for physical port MTU change. */ 635 if (repr->port->type != NFP_PORT_PHYS_PORT) 636 return 0; 637 638 if (!(app_priv->flower_ext_feats & NFP_FL_NBI_MTU_SETTING)) { 639 nfp_err(app->cpp, "Physical port MTU setting not supported\n"); 640 return -EINVAL; 641 } 642 643 spin_lock_bh(&app_priv->mtu_conf.lock); 644 app_priv->mtu_conf.ack = false; 645 app_priv->mtu_conf.requested_val = new_mtu; 646 app_priv->mtu_conf.portnum = repr->dst->u.port_info.port_id; 647 spin_unlock_bh(&app_priv->mtu_conf.lock); 648 649 err = nfp_flower_cmsg_portmod(repr, netif_carrier_ok(netdev), new_mtu, 650 true); 651 if (err) { 652 spin_lock_bh(&app_priv->mtu_conf.lock); 653 app_priv->mtu_conf.requested_val = 0; 654 spin_unlock_bh(&app_priv->mtu_conf.lock); 655 return err; 656 } 657 658 /* Wait for fw to ack the change. */ 659 ack = wait_event_timeout(app_priv->mtu_conf.wait_q, 660 nfp_flower_check_ack(app_priv), 661 msecs_to_jiffies(10)); 662 663 if (!ack) { 664 spin_lock_bh(&app_priv->mtu_conf.lock); 665 app_priv->mtu_conf.requested_val = 0; 666 spin_unlock_bh(&app_priv->mtu_conf.lock); 667 nfp_warn(app->cpp, "MTU change not verified with fw\n"); 668 return -EIO; 669 } 670 671 return 0; 672 } 673 674 static int nfp_flower_start(struct nfp_app *app) 675 { 676 struct nfp_flower_priv *app_priv = app->priv; 677 int err; 678 679 if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG) { 680 err = nfp_flower_lag_reset(&app_priv->nfp_lag); 681 if (err) 682 return err; 683 684 err = register_netdevice_notifier(&app_priv->nfp_lag.lag_nb); 685 if (err) 686 return err; 687 } 688 689 return nfp_tunnel_config_start(app); 690 } 691 692 static void nfp_flower_stop(struct nfp_app *app) 693 { 694 struct nfp_flower_priv *app_priv = app->priv; 695 696 if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG) 697 unregister_netdevice_notifier(&app_priv->nfp_lag.lag_nb); 698 699 nfp_tunnel_config_stop(app); 700 } 701 702 const struct nfp_app_type app_flower = { 703 .id = NFP_APP_FLOWER_NIC, 704 .name = "flower", 705 706 .ctrl_cap_mask = ~0U, 707 .ctrl_has_meta = true, 708 709 .extra_cap = nfp_flower_extra_cap, 710 711 .init = nfp_flower_init, 712 .clean = nfp_flower_clean, 713 714 .repr_change_mtu = nfp_flower_repr_change_mtu, 715 716 .vnic_alloc = nfp_flower_vnic_alloc, 717 .vnic_init = nfp_flower_vnic_init, 718 .vnic_clean = nfp_flower_vnic_clean, 719 720 .repr_init = nfp_flower_repr_netdev_init, 721 .repr_preclean = nfp_flower_repr_netdev_preclean, 722 .repr_clean = nfp_flower_repr_netdev_clean, 723 724 .repr_open = nfp_flower_repr_netdev_open, 725 .repr_stop = nfp_flower_repr_netdev_stop, 726 727 .start = nfp_flower_start, 728 .stop = nfp_flower_stop, 729 730 .ctrl_msg_rx = nfp_flower_cmsg_rx, 731 732 .sriov_enable = nfp_flower_sriov_enable, 733 .sriov_disable = nfp_flower_sriov_disable, 734 735 .eswitch_mode_get = eswitch_mode_get, 736 .repr_get = nfp_flower_repr_get, 737 738 .setup_tc = nfp_flower_setup_tc, 739 }; 740