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 #define NFP_FLOWER_FRAME_HEADROOM 158 56 57 static const char *nfp_flower_extra_cap(struct nfp_app *app, struct nfp_net *nn) 58 { 59 return "FLOWER"; 60 } 61 62 static enum devlink_eswitch_mode eswitch_mode_get(struct nfp_app *app) 63 { 64 return DEVLINK_ESWITCH_MODE_SWITCHDEV; 65 } 66 67 static enum nfp_repr_type 68 nfp_flower_repr_get_type_and_port(struct nfp_app *app, u32 port_id, u8 *port) 69 { 70 switch (FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE, port_id)) { 71 case NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT: 72 *port = FIELD_GET(NFP_FLOWER_CMSG_PORT_PHYS_PORT_NUM, 73 port_id); 74 return NFP_REPR_TYPE_PHYS_PORT; 75 76 case NFP_FLOWER_CMSG_PORT_TYPE_PCIE_PORT: 77 *port = FIELD_GET(NFP_FLOWER_CMSG_PORT_VNIC, port_id); 78 if (FIELD_GET(NFP_FLOWER_CMSG_PORT_VNIC_TYPE, port_id) == 79 NFP_FLOWER_CMSG_PORT_VNIC_TYPE_PF) 80 return NFP_REPR_TYPE_PF; 81 else 82 return NFP_REPR_TYPE_VF; 83 } 84 85 return NFP_FLOWER_CMSG_PORT_TYPE_UNSPEC; 86 } 87 88 static struct net_device * 89 nfp_flower_repr_get(struct nfp_app *app, u32 port_id) 90 { 91 enum nfp_repr_type repr_type; 92 struct nfp_reprs *reprs; 93 u8 port = 0; 94 95 repr_type = nfp_flower_repr_get_type_and_port(app, port_id, &port); 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 tc_setup_cb_egdev_unregister(netdev, nfp_flower_setup_tc_egress_cb, 191 netdev_priv(netdev)); 192 } 193 194 static void 195 nfp_flower_repr_netdev_preclean(struct nfp_app *app, struct net_device *netdev) 196 { 197 struct nfp_repr *repr = netdev_priv(netdev); 198 struct nfp_flower_priv *priv = app->priv; 199 atomic_t *replies = &priv->reify_replies; 200 int err; 201 202 atomic_set(replies, 0); 203 err = nfp_flower_cmsg_portreify(repr, false); 204 if (err) { 205 nfp_warn(app->cpp, "Failed to notify firmware about repr destruction\n"); 206 return; 207 } 208 209 nfp_flower_wait_repr_reify(app, replies, 1); 210 } 211 212 static void nfp_flower_sriov_disable(struct nfp_app *app) 213 { 214 struct nfp_flower_priv *priv = app->priv; 215 216 if (!priv->nn) 217 return; 218 219 nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_VF); 220 } 221 222 static int 223 nfp_flower_spawn_vnic_reprs(struct nfp_app *app, 224 enum nfp_flower_cmsg_port_vnic_type vnic_type, 225 enum nfp_repr_type repr_type, unsigned int cnt) 226 { 227 u8 nfp_pcie = nfp_cppcore_pcie_unit(app->pf->cpp); 228 struct nfp_flower_priv *priv = app->priv; 229 atomic_t *replies = &priv->reify_replies; 230 enum nfp_port_type port_type; 231 struct nfp_reprs *reprs; 232 int i, err, reify_cnt; 233 const u8 queue = 0; 234 235 port_type = repr_type == NFP_REPR_TYPE_PF ? NFP_PORT_PF_PORT : 236 NFP_PORT_VF_PORT; 237 238 reprs = nfp_reprs_alloc(cnt); 239 if (!reprs) 240 return -ENOMEM; 241 242 for (i = 0; i < cnt; i++) { 243 struct net_device *repr; 244 struct nfp_port *port; 245 u32 port_id; 246 247 repr = nfp_repr_alloc(app); 248 if (!repr) { 249 err = -ENOMEM; 250 goto err_reprs_clean; 251 } 252 RCU_INIT_POINTER(reprs->reprs[i], repr); 253 254 /* For now we only support 1 PF */ 255 WARN_ON(repr_type == NFP_REPR_TYPE_PF && i); 256 257 port = nfp_port_alloc(app, port_type, repr); 258 if (repr_type == NFP_REPR_TYPE_PF) { 259 port->pf_id = i; 260 port->vnic = priv->nn->dp.ctrl_bar; 261 } else { 262 port->pf_id = 0; 263 port->vf_id = i; 264 port->vnic = 265 app->pf->vf_cfg_mem + i * NFP_NET_CFG_BAR_SZ; 266 } 267 268 eth_hw_addr_random(repr); 269 270 port_id = nfp_flower_cmsg_pcie_port(nfp_pcie, vnic_type, 271 i, queue); 272 err = nfp_repr_init(app, repr, 273 port_id, port, priv->nn->dp.netdev); 274 if (err) { 275 nfp_port_free(port); 276 goto err_reprs_clean; 277 } 278 279 nfp_info(app->cpp, "%s%d Representor(%s) created\n", 280 repr_type == NFP_REPR_TYPE_PF ? "PF" : "VF", i, 281 repr->name); 282 } 283 284 nfp_app_reprs_set(app, repr_type, reprs); 285 286 atomic_set(replies, 0); 287 reify_cnt = nfp_flower_reprs_reify(app, repr_type, true); 288 if (reify_cnt < 0) { 289 err = reify_cnt; 290 nfp_warn(app->cpp, "Failed to notify firmware about repr creation\n"); 291 goto err_reprs_remove; 292 } 293 294 err = nfp_flower_wait_repr_reify(app, replies, reify_cnt); 295 if (err) 296 goto err_reprs_remove; 297 298 return 0; 299 err_reprs_remove: 300 reprs = nfp_app_reprs_set(app, repr_type, NULL); 301 err_reprs_clean: 302 nfp_reprs_clean_and_free(app, reprs); 303 return err; 304 } 305 306 static int nfp_flower_sriov_enable(struct nfp_app *app, int num_vfs) 307 { 308 struct nfp_flower_priv *priv = app->priv; 309 310 if (!priv->nn) 311 return 0; 312 313 return nfp_flower_spawn_vnic_reprs(app, 314 NFP_FLOWER_CMSG_PORT_VNIC_TYPE_VF, 315 NFP_REPR_TYPE_VF, num_vfs); 316 } 317 318 static int 319 nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv) 320 { 321 struct nfp_eth_table *eth_tbl = app->pf->eth_tbl; 322 atomic_t *replies = &priv->reify_replies; 323 struct sk_buff *ctrl_skb; 324 struct nfp_reprs *reprs; 325 int err, reify_cnt; 326 unsigned int i; 327 328 ctrl_skb = nfp_flower_cmsg_mac_repr_start(app, eth_tbl->count); 329 if (!ctrl_skb) 330 return -ENOMEM; 331 332 reprs = nfp_reprs_alloc(eth_tbl->max_index + 1); 333 if (!reprs) { 334 err = -ENOMEM; 335 goto err_free_ctrl_skb; 336 } 337 338 for (i = 0; i < eth_tbl->count; i++) { 339 unsigned int phys_port = eth_tbl->ports[i].index; 340 struct net_device *repr; 341 struct nfp_port *port; 342 u32 cmsg_port_id; 343 344 repr = nfp_repr_alloc(app); 345 if (!repr) { 346 err = -ENOMEM; 347 goto err_reprs_clean; 348 } 349 RCU_INIT_POINTER(reprs->reprs[phys_port], repr); 350 351 port = nfp_port_alloc(app, NFP_PORT_PHYS_PORT, repr); 352 if (IS_ERR(port)) { 353 err = PTR_ERR(port); 354 goto err_reprs_clean; 355 } 356 err = nfp_port_init_phy_port(app->pf, app, port, i); 357 if (err) { 358 nfp_port_free(port); 359 goto err_reprs_clean; 360 } 361 362 SET_NETDEV_DEV(repr, &priv->nn->pdev->dev); 363 nfp_net_get_mac_addr(app->pf, port); 364 365 cmsg_port_id = nfp_flower_cmsg_phys_port(phys_port); 366 err = nfp_repr_init(app, repr, 367 cmsg_port_id, port, priv->nn->dp.netdev); 368 if (err) { 369 nfp_port_free(port); 370 goto err_reprs_clean; 371 } 372 373 nfp_flower_cmsg_mac_repr_add(ctrl_skb, i, 374 eth_tbl->ports[i].nbi, 375 eth_tbl->ports[i].base, 376 phys_port); 377 378 nfp_info(app->cpp, "Phys Port %d Representor(%s) created\n", 379 phys_port, repr->name); 380 } 381 382 nfp_app_reprs_set(app, NFP_REPR_TYPE_PHYS_PORT, reprs); 383 384 /* The REIFY/MAC_REPR control messages should be sent after the MAC 385 * representors are registered using nfp_app_reprs_set(). This is 386 * because the firmware may respond with control messages for the 387 * MAC representors, f.e. to provide the driver with information 388 * about their state, and without registration the driver will drop 389 * any such messages. 390 */ 391 atomic_set(replies, 0); 392 reify_cnt = nfp_flower_reprs_reify(app, NFP_REPR_TYPE_PHYS_PORT, true); 393 if (reify_cnt < 0) { 394 err = reify_cnt; 395 nfp_warn(app->cpp, "Failed to notify firmware about repr creation\n"); 396 goto err_reprs_remove; 397 } 398 399 err = nfp_flower_wait_repr_reify(app, replies, reify_cnt); 400 if (err) 401 goto err_reprs_remove; 402 403 nfp_ctrl_tx(app->ctrl, ctrl_skb); 404 405 return 0; 406 err_reprs_remove: 407 reprs = nfp_app_reprs_set(app, NFP_REPR_TYPE_PHYS_PORT, NULL); 408 err_reprs_clean: 409 nfp_reprs_clean_and_free(app, reprs); 410 err_free_ctrl_skb: 411 kfree_skb(ctrl_skb); 412 return err; 413 } 414 415 static int nfp_flower_vnic_alloc(struct nfp_app *app, struct nfp_net *nn, 416 unsigned int id) 417 { 418 if (id > 0) { 419 nfp_warn(app->cpp, "FlowerNIC doesn't support more than one data vNIC\n"); 420 goto err_invalid_port; 421 } 422 423 eth_hw_addr_random(nn->dp.netdev); 424 netif_keep_dst(nn->dp.netdev); 425 426 return 0; 427 428 err_invalid_port: 429 nn->port = nfp_port_alloc(app, NFP_PORT_INVALID, nn->dp.netdev); 430 return PTR_ERR_OR_ZERO(nn->port); 431 } 432 433 static void nfp_flower_vnic_clean(struct nfp_app *app, struct nfp_net *nn) 434 { 435 struct nfp_flower_priv *priv = app->priv; 436 437 if (app->pf->num_vfs) 438 nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_VF); 439 nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PF); 440 nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PHYS_PORT); 441 442 priv->nn = NULL; 443 } 444 445 static int nfp_flower_vnic_init(struct nfp_app *app, struct nfp_net *nn) 446 { 447 struct nfp_flower_priv *priv = app->priv; 448 int err; 449 450 priv->nn = nn; 451 452 err = nfp_flower_spawn_phy_reprs(app, app->priv); 453 if (err) 454 goto err_clear_nn; 455 456 err = nfp_flower_spawn_vnic_reprs(app, 457 NFP_FLOWER_CMSG_PORT_VNIC_TYPE_PF, 458 NFP_REPR_TYPE_PF, 1); 459 if (err) 460 goto err_destroy_reprs_phy; 461 462 if (app->pf->num_vfs) { 463 err = nfp_flower_spawn_vnic_reprs(app, 464 NFP_FLOWER_CMSG_PORT_VNIC_TYPE_VF, 465 NFP_REPR_TYPE_VF, 466 app->pf->num_vfs); 467 if (err) 468 goto err_destroy_reprs_pf; 469 } 470 471 return 0; 472 473 err_destroy_reprs_pf: 474 nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PF); 475 err_destroy_reprs_phy: 476 nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PHYS_PORT); 477 err_clear_nn: 478 priv->nn = NULL; 479 return err; 480 } 481 482 static int nfp_flower_init(struct nfp_app *app) 483 { 484 const struct nfp_pf *pf = app->pf; 485 struct nfp_flower_priv *app_priv; 486 u64 version, features; 487 int err; 488 489 if (!pf->eth_tbl) { 490 nfp_warn(app->cpp, "FlowerNIC requires eth table\n"); 491 return -EINVAL; 492 } 493 494 if (!pf->mac_stats_bar) { 495 nfp_warn(app->cpp, "FlowerNIC requires mac_stats BAR\n"); 496 return -EINVAL; 497 } 498 499 if (!pf->vf_cfg_bar) { 500 nfp_warn(app->cpp, "FlowerNIC requires vf_cfg BAR\n"); 501 return -EINVAL; 502 } 503 504 version = nfp_rtsym_read_le(app->pf->rtbl, "hw_flower_version", &err); 505 if (err) { 506 nfp_warn(app->cpp, "FlowerNIC requires hw_flower_version memory symbol\n"); 507 return err; 508 } 509 510 /* We need to ensure hardware has enough flower capabilities. */ 511 if (version != NFP_FLOWER_ALLOWED_VER) { 512 nfp_warn(app->cpp, "FlowerNIC: unsupported firmware version\n"); 513 return -EINVAL; 514 } 515 516 app_priv = vzalloc(sizeof(struct nfp_flower_priv)); 517 if (!app_priv) 518 return -ENOMEM; 519 520 app->priv = app_priv; 521 app_priv->app = app; 522 skb_queue_head_init(&app_priv->cmsg_skbs_high); 523 skb_queue_head_init(&app_priv->cmsg_skbs_low); 524 INIT_WORK(&app_priv->cmsg_work, nfp_flower_cmsg_process_rx); 525 init_waitqueue_head(&app_priv->reify_wait_queue); 526 527 init_waitqueue_head(&app_priv->mtu_conf.wait_q); 528 spin_lock_init(&app_priv->mtu_conf.lock); 529 530 err = nfp_flower_metadata_init(app); 531 if (err) 532 goto err_free_app_priv; 533 534 /* Extract the extra features supported by the firmware. */ 535 features = nfp_rtsym_read_le(app->pf->rtbl, 536 "_abi_flower_extra_features", &err); 537 if (err) 538 app_priv->flower_ext_feats = 0; 539 else 540 app_priv->flower_ext_feats = features; 541 542 return 0; 543 544 err_free_app_priv: 545 vfree(app->priv); 546 return err; 547 } 548 549 static void nfp_flower_clean(struct nfp_app *app) 550 { 551 struct nfp_flower_priv *app_priv = app->priv; 552 553 skb_queue_purge(&app_priv->cmsg_skbs_high); 554 skb_queue_purge(&app_priv->cmsg_skbs_low); 555 flush_work(&app_priv->cmsg_work); 556 557 nfp_flower_metadata_cleanup(app); 558 vfree(app->priv); 559 app->priv = NULL; 560 } 561 562 static int 563 nfp_flower_check_mtu(struct nfp_app *app, struct net_device *netdev, 564 int new_mtu) 565 { 566 /* The flower fw reserves NFP_FLOWER_FRAME_HEADROOM bytes of the 567 * supported max MTU to allow for appending tunnel headers. To prevent 568 * unexpected behaviour this needs to be accounted for. 569 */ 570 if (new_mtu > netdev->max_mtu - NFP_FLOWER_FRAME_HEADROOM) { 571 nfp_err(app->cpp, "New MTU (%d) is not valid\n", new_mtu); 572 return -EINVAL; 573 } 574 575 return 0; 576 } 577 578 static bool nfp_flower_check_ack(struct nfp_flower_priv *app_priv) 579 { 580 bool ret; 581 582 spin_lock_bh(&app_priv->mtu_conf.lock); 583 ret = app_priv->mtu_conf.ack; 584 spin_unlock_bh(&app_priv->mtu_conf.lock); 585 586 return ret; 587 } 588 589 static int 590 nfp_flower_repr_change_mtu(struct nfp_app *app, struct net_device *netdev, 591 int new_mtu) 592 { 593 struct nfp_flower_priv *app_priv = app->priv; 594 struct nfp_repr *repr = netdev_priv(netdev); 595 int err, ack; 596 597 /* Only need to config FW for physical port MTU change. */ 598 if (repr->port->type != NFP_PORT_PHYS_PORT) 599 return 0; 600 601 if (!(app_priv->flower_ext_feats & NFP_FL_NBI_MTU_SETTING)) { 602 nfp_err(app->cpp, "Physical port MTU setting not supported\n"); 603 return -EINVAL; 604 } 605 606 spin_lock_bh(&app_priv->mtu_conf.lock); 607 app_priv->mtu_conf.ack = false; 608 app_priv->mtu_conf.requested_val = new_mtu; 609 app_priv->mtu_conf.portnum = repr->dst->u.port_info.port_id; 610 spin_unlock_bh(&app_priv->mtu_conf.lock); 611 612 err = nfp_flower_cmsg_portmod(repr, netif_carrier_ok(netdev), new_mtu, 613 true); 614 if (err) { 615 spin_lock_bh(&app_priv->mtu_conf.lock); 616 app_priv->mtu_conf.requested_val = 0; 617 spin_unlock_bh(&app_priv->mtu_conf.lock); 618 return err; 619 } 620 621 /* Wait for fw to ack the change. */ 622 ack = wait_event_timeout(app_priv->mtu_conf.wait_q, 623 nfp_flower_check_ack(app_priv), 624 msecs_to_jiffies(10)); 625 626 if (!ack) { 627 spin_lock_bh(&app_priv->mtu_conf.lock); 628 app_priv->mtu_conf.requested_val = 0; 629 spin_unlock_bh(&app_priv->mtu_conf.lock); 630 nfp_warn(app->cpp, "MTU change not verified with fw\n"); 631 return -EIO; 632 } 633 634 return 0; 635 } 636 637 static int nfp_flower_start(struct nfp_app *app) 638 { 639 return nfp_tunnel_config_start(app); 640 } 641 642 static void nfp_flower_stop(struct nfp_app *app) 643 { 644 nfp_tunnel_config_stop(app); 645 } 646 647 const struct nfp_app_type app_flower = { 648 .id = NFP_APP_FLOWER_NIC, 649 .name = "flower", 650 651 .ctrl_cap_mask = ~0U, 652 .ctrl_has_meta = true, 653 654 .extra_cap = nfp_flower_extra_cap, 655 656 .init = nfp_flower_init, 657 .clean = nfp_flower_clean, 658 659 .check_mtu = nfp_flower_check_mtu, 660 .repr_change_mtu = nfp_flower_repr_change_mtu, 661 662 .vnic_alloc = nfp_flower_vnic_alloc, 663 .vnic_init = nfp_flower_vnic_init, 664 .vnic_clean = nfp_flower_vnic_clean, 665 666 .repr_init = nfp_flower_repr_netdev_init, 667 .repr_preclean = nfp_flower_repr_netdev_preclean, 668 .repr_clean = nfp_flower_repr_netdev_clean, 669 670 .repr_open = nfp_flower_repr_netdev_open, 671 .repr_stop = nfp_flower_repr_netdev_stop, 672 673 .start = nfp_flower_start, 674 .stop = nfp_flower_stop, 675 676 .ctrl_msg_rx = nfp_flower_cmsg_rx, 677 678 .sriov_enable = nfp_flower_sriov_enable, 679 .sriov_disable = nfp_flower_sriov_disable, 680 681 .eswitch_mode_get = eswitch_mode_get, 682 .repr_get = nfp_flower_repr_get, 683 684 .setup_tc = nfp_flower_setup_tc, 685 }; 686