linux/drivers/net/ethernet/netronome/nfp/flower/main.c
<<
>>
Prefs
   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
  55static const char *nfp_flower_extra_cap(struct nfp_app *app, struct nfp_net *nn)
  56{
  57        return "FLOWER";
  58}
  59
  60static enum devlink_eswitch_mode eswitch_mode_get(struct nfp_app *app)
  61{
  62        return DEVLINK_ESWITCH_MODE_SWITCHDEV;
  63}
  64
  65static enum nfp_repr_type
  66nfp_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_FLOWER_CMSG_PORT_TYPE_UNSPEC;
  84}
  85
  86static struct net_device *
  87nfp_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
  95        reprs = rcu_dereference(app->reprs[repr_type]);
  96        if (!reprs)
  97                return NULL;
  98
  99        if (port >= reprs->num_reprs)
 100                return NULL;
 101
 102        return rcu_dereference(reprs->reprs[port]);
 103}
 104
 105static int
 106nfp_flower_reprs_reify(struct nfp_app *app, enum nfp_repr_type type,
 107                       bool exists)
 108{
 109        struct nfp_reprs *reprs;
 110        int i, err, count = 0;
 111
 112        reprs = rcu_dereference_protected(app->reprs[type],
 113                                          lockdep_is_held(&app->pf->lock));
 114        if (!reprs)
 115                return 0;
 116
 117        for (i = 0; i < reprs->num_reprs; i++) {
 118                struct net_device *netdev;
 119
 120                netdev = nfp_repr_get_locked(app, reprs, i);
 121                if (netdev) {
 122                        struct nfp_repr *repr = netdev_priv(netdev);
 123
 124                        err = nfp_flower_cmsg_portreify(repr, exists);
 125                        if (err)
 126                                return err;
 127                        count++;
 128                }
 129        }
 130
 131        return count;
 132}
 133
 134static int
 135nfp_flower_wait_repr_reify(struct nfp_app *app, atomic_t *replies, int tot_repl)
 136{
 137        struct nfp_flower_priv *priv = app->priv;
 138        int err;
 139
 140        if (!tot_repl)
 141                return 0;
 142
 143        lockdep_assert_held(&app->pf->lock);
 144        err = wait_event_interruptible_timeout(priv->reify_wait_queue,
 145                                               atomic_read(replies) >= tot_repl,
 146                                               msecs_to_jiffies(10));
 147        if (err <= 0) {
 148                nfp_warn(app->cpp, "Not all reprs responded to reify\n");
 149                return -EIO;
 150        }
 151
 152        return 0;
 153}
 154
 155static int
 156nfp_flower_repr_netdev_open(struct nfp_app *app, struct nfp_repr *repr)
 157{
 158        int err;
 159
 160        err = nfp_flower_cmsg_portmod(repr, true);
 161        if (err)
 162                return err;
 163
 164        netif_tx_wake_all_queues(repr->netdev);
 165
 166        return 0;
 167}
 168
 169static int
 170nfp_flower_repr_netdev_stop(struct nfp_app *app, struct nfp_repr *repr)
 171{
 172        netif_tx_disable(repr->netdev);
 173
 174        return nfp_flower_cmsg_portmod(repr, false);
 175}
 176
 177static int
 178nfp_flower_repr_netdev_init(struct nfp_app *app, struct net_device *netdev)
 179{
 180        return tc_setup_cb_egdev_register(netdev,
 181                                          nfp_flower_setup_tc_egress_cb,
 182                                          netdev_priv(netdev));
 183}
 184
 185static void
 186nfp_flower_repr_netdev_clean(struct nfp_app *app, struct net_device *netdev)
 187{
 188        tc_setup_cb_egdev_unregister(netdev, nfp_flower_setup_tc_egress_cb,
 189                                     netdev_priv(netdev));
 190}
 191
 192static void
 193nfp_flower_repr_netdev_preclean(struct nfp_app *app, struct net_device *netdev)
 194{
 195        struct nfp_repr *repr = netdev_priv(netdev);
 196        struct nfp_flower_priv *priv = app->priv;
 197        atomic_t *replies = &priv->reify_replies;
 198        int err;
 199
 200        atomic_set(replies, 0);
 201        err = nfp_flower_cmsg_portreify(repr, false);
 202        if (err) {
 203                nfp_warn(app->cpp, "Failed to notify firmware about repr destruction\n");
 204                return;
 205        }
 206
 207        nfp_flower_wait_repr_reify(app, replies, 1);
 208}
 209
 210static void nfp_flower_sriov_disable(struct nfp_app *app)
 211{
 212        struct nfp_flower_priv *priv = app->priv;
 213
 214        if (!priv->nn)
 215                return;
 216
 217        nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_VF);
 218}
 219
 220static int
 221nfp_flower_spawn_vnic_reprs(struct nfp_app *app,
 222                            enum nfp_flower_cmsg_port_vnic_type vnic_type,
 223                            enum nfp_repr_type repr_type, unsigned int cnt)
 224{
 225        u8 nfp_pcie = nfp_cppcore_pcie_unit(app->pf->cpp);
 226        struct nfp_flower_priv *priv = app->priv;
 227        atomic_t *replies = &priv->reify_replies;
 228        enum nfp_port_type port_type;
 229        struct nfp_reprs *reprs;
 230        int i, err, reify_cnt;
 231        const u8 queue = 0;
 232
 233        port_type = repr_type == NFP_REPR_TYPE_PF ? NFP_PORT_PF_PORT :
 234                                                    NFP_PORT_VF_PORT;
 235
 236        reprs = nfp_reprs_alloc(cnt);
 237        if (!reprs)
 238                return -ENOMEM;
 239
 240        for (i = 0; i < cnt; i++) {
 241                struct net_device *repr;
 242                struct nfp_port *port;
 243                u32 port_id;
 244
 245                repr = nfp_repr_alloc(app);
 246                if (!repr) {
 247                        err = -ENOMEM;
 248                        goto err_reprs_clean;
 249                }
 250                RCU_INIT_POINTER(reprs->reprs[i], repr);
 251
 252                /* For now we only support 1 PF */
 253                WARN_ON(repr_type == NFP_REPR_TYPE_PF && i);
 254
 255                port = nfp_port_alloc(app, port_type, repr);
 256                if (repr_type == NFP_REPR_TYPE_PF) {
 257                        port->pf_id = i;
 258                        port->vnic = priv->nn->dp.ctrl_bar;
 259                } else {
 260                        port->pf_id = 0;
 261                        port->vf_id = i;
 262                        port->vnic =
 263                                app->pf->vf_cfg_mem + i * NFP_NET_CFG_BAR_SZ;
 264                }
 265
 266                eth_hw_addr_random(repr);
 267
 268                port_id = nfp_flower_cmsg_pcie_port(nfp_pcie, vnic_type,
 269                                                    i, queue);
 270                err = nfp_repr_init(app, repr,
 271                                    port_id, port, priv->nn->dp.netdev);
 272                if (err) {
 273                        nfp_port_free(port);
 274                        goto err_reprs_clean;
 275                }
 276
 277                nfp_info(app->cpp, "%s%d Representor(%s) created\n",
 278                         repr_type == NFP_REPR_TYPE_PF ? "PF" : "VF", i,
 279                         repr->name);
 280        }
 281
 282        nfp_app_reprs_set(app, repr_type, reprs);
 283
 284        atomic_set(replies, 0);
 285        reify_cnt = nfp_flower_reprs_reify(app, repr_type, true);
 286        if (reify_cnt < 0) {
 287                err = reify_cnt;
 288                nfp_warn(app->cpp, "Failed to notify firmware about repr creation\n");
 289                goto err_reprs_remove;
 290        }
 291
 292        err = nfp_flower_wait_repr_reify(app, replies, reify_cnt);
 293        if (err)
 294                goto err_reprs_remove;
 295
 296        return 0;
 297err_reprs_remove:
 298        reprs = nfp_app_reprs_set(app, repr_type, NULL);
 299err_reprs_clean:
 300        nfp_reprs_clean_and_free(app, reprs);
 301        return err;
 302}
 303
 304static int nfp_flower_sriov_enable(struct nfp_app *app, int num_vfs)
 305{
 306        struct nfp_flower_priv *priv = app->priv;
 307
 308        if (!priv->nn)
 309                return 0;
 310
 311        return nfp_flower_spawn_vnic_reprs(app,
 312                                           NFP_FLOWER_CMSG_PORT_VNIC_TYPE_VF,
 313                                           NFP_REPR_TYPE_VF, num_vfs);
 314}
 315
 316static int
 317nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv)
 318{
 319        struct nfp_eth_table *eth_tbl = app->pf->eth_tbl;
 320        atomic_t *replies = &priv->reify_replies;
 321        struct sk_buff *ctrl_skb;
 322        struct nfp_reprs *reprs;
 323        int err, reify_cnt;
 324        unsigned int i;
 325
 326        ctrl_skb = nfp_flower_cmsg_mac_repr_start(app, eth_tbl->count);
 327        if (!ctrl_skb)
 328                return -ENOMEM;
 329
 330        reprs = nfp_reprs_alloc(eth_tbl->max_index + 1);
 331        if (!reprs) {
 332                err = -ENOMEM;
 333                goto err_free_ctrl_skb;
 334        }
 335
 336        for (i = 0; i < eth_tbl->count; i++) {
 337                unsigned int phys_port = eth_tbl->ports[i].index;
 338                struct net_device *repr;
 339                struct nfp_port *port;
 340                u32 cmsg_port_id;
 341
 342                repr = nfp_repr_alloc(app);
 343                if (!repr) {
 344                        err = -ENOMEM;
 345                        goto err_reprs_clean;
 346                }
 347                RCU_INIT_POINTER(reprs->reprs[phys_port], repr);
 348
 349                port = nfp_port_alloc(app, NFP_PORT_PHYS_PORT, repr);
 350                if (IS_ERR(port)) {
 351                        err = PTR_ERR(port);
 352                        goto err_reprs_clean;
 353                }
 354                err = nfp_port_init_phy_port(app->pf, app, port, i);
 355                if (err) {
 356                        nfp_port_free(port);
 357                        goto err_reprs_clean;
 358                }
 359
 360                SET_NETDEV_DEV(repr, &priv->nn->pdev->dev);
 361                nfp_net_get_mac_addr(app->pf, port);
 362
 363                cmsg_port_id = nfp_flower_cmsg_phys_port(phys_port);
 364                err = nfp_repr_init(app, repr,
 365                                    cmsg_port_id, port, priv->nn->dp.netdev);
 366                if (err) {
 367                        nfp_port_free(port);
 368                        goto err_reprs_clean;
 369                }
 370
 371                nfp_flower_cmsg_mac_repr_add(ctrl_skb, i,
 372                                             eth_tbl->ports[i].nbi,
 373                                             eth_tbl->ports[i].base,
 374                                             phys_port);
 375
 376                nfp_info(app->cpp, "Phys Port %d Representor(%s) created\n",
 377                         phys_port, repr->name);
 378        }
 379
 380        nfp_app_reprs_set(app, NFP_REPR_TYPE_PHYS_PORT, reprs);
 381
 382        /* The REIFY/MAC_REPR control messages should be sent after the MAC
 383         * representors are registered using nfp_app_reprs_set().  This is
 384         * because the firmware may respond with control messages for the
 385         * MAC representors, f.e. to provide the driver with information
 386         * about their state, and without registration the driver will drop
 387         * any such messages.
 388         */
 389        atomic_set(replies, 0);
 390        reify_cnt = nfp_flower_reprs_reify(app, NFP_REPR_TYPE_PHYS_PORT, true);
 391        if (reify_cnt < 0) {
 392                err = reify_cnt;
 393                nfp_warn(app->cpp, "Failed to notify firmware about repr creation\n");
 394                goto err_reprs_remove;
 395        }
 396
 397        err = nfp_flower_wait_repr_reify(app, replies, reify_cnt);
 398        if (err)
 399                goto err_reprs_remove;
 400
 401        nfp_ctrl_tx(app->ctrl, ctrl_skb);
 402
 403        return 0;
 404err_reprs_remove:
 405        reprs = nfp_app_reprs_set(app, NFP_REPR_TYPE_PHYS_PORT, NULL);
 406err_reprs_clean:
 407        nfp_reprs_clean_and_free(app, reprs);
 408err_free_ctrl_skb:
 409        kfree_skb(ctrl_skb);
 410        return err;
 411}
 412
 413static int nfp_flower_vnic_alloc(struct nfp_app *app, struct nfp_net *nn,
 414                                 unsigned int id)
 415{
 416        if (id > 0) {
 417                nfp_warn(app->cpp, "FlowerNIC doesn't support more than one data vNIC\n");
 418                goto err_invalid_port;
 419        }
 420
 421        eth_hw_addr_random(nn->dp.netdev);
 422        netif_keep_dst(nn->dp.netdev);
 423
 424        return 0;
 425
 426err_invalid_port:
 427        nn->port = nfp_port_alloc(app, NFP_PORT_INVALID, nn->dp.netdev);
 428        return PTR_ERR_OR_ZERO(nn->port);
 429}
 430
 431static void nfp_flower_vnic_clean(struct nfp_app *app, struct nfp_net *nn)
 432{
 433        struct nfp_flower_priv *priv = app->priv;
 434
 435        if (app->pf->num_vfs)
 436                nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_VF);
 437        nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PF);
 438        nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PHYS_PORT);
 439
 440        priv->nn = NULL;
 441}
 442
 443static int nfp_flower_vnic_init(struct nfp_app *app, struct nfp_net *nn)
 444{
 445        struct nfp_flower_priv *priv = app->priv;
 446        int err;
 447
 448        priv->nn = nn;
 449
 450        err = nfp_flower_spawn_phy_reprs(app, app->priv);
 451        if (err)
 452                goto err_clear_nn;
 453
 454        err = nfp_flower_spawn_vnic_reprs(app,
 455                                          NFP_FLOWER_CMSG_PORT_VNIC_TYPE_PF,
 456                                          NFP_REPR_TYPE_PF, 1);
 457        if (err)
 458                goto err_destroy_reprs_phy;
 459
 460        if (app->pf->num_vfs) {
 461                err = nfp_flower_spawn_vnic_reprs(app,
 462                                                  NFP_FLOWER_CMSG_PORT_VNIC_TYPE_VF,
 463                                                  NFP_REPR_TYPE_VF,
 464                                                  app->pf->num_vfs);
 465                if (err)
 466                        goto err_destroy_reprs_pf;
 467        }
 468
 469        return 0;
 470
 471err_destroy_reprs_pf:
 472        nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PF);
 473err_destroy_reprs_phy:
 474        nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PHYS_PORT);
 475err_clear_nn:
 476        priv->nn = NULL;
 477        return err;
 478}
 479
 480static int nfp_flower_init(struct nfp_app *app)
 481{
 482        const struct nfp_pf *pf = app->pf;
 483        struct nfp_flower_priv *app_priv;
 484        u64 version, features;
 485        int err;
 486
 487        if (!pf->eth_tbl) {
 488                nfp_warn(app->cpp, "FlowerNIC requires eth table\n");
 489                return -EINVAL;
 490        }
 491
 492        if (!pf->mac_stats_bar) {
 493                nfp_warn(app->cpp, "FlowerNIC requires mac_stats BAR\n");
 494                return -EINVAL;
 495        }
 496
 497        if (!pf->vf_cfg_bar) {
 498                nfp_warn(app->cpp, "FlowerNIC requires vf_cfg BAR\n");
 499                return -EINVAL;
 500        }
 501
 502        version = nfp_rtsym_read_le(app->pf->rtbl, "hw_flower_version", &err);
 503        if (err) {
 504                nfp_warn(app->cpp, "FlowerNIC requires hw_flower_version memory symbol\n");
 505                return err;
 506        }
 507
 508        /* We need to ensure hardware has enough flower capabilities. */
 509        if (version != NFP_FLOWER_ALLOWED_VER) {
 510                nfp_warn(app->cpp, "FlowerNIC: unsupported firmware version\n");
 511                return -EINVAL;
 512        }
 513
 514        app_priv = vzalloc(sizeof(struct nfp_flower_priv));
 515        if (!app_priv)
 516                return -ENOMEM;
 517
 518        app->priv = app_priv;
 519        app_priv->app = app;
 520        skb_queue_head_init(&app_priv->cmsg_skbs);
 521        INIT_WORK(&app_priv->cmsg_work, nfp_flower_cmsg_process_rx);
 522        init_waitqueue_head(&app_priv->reify_wait_queue);
 523
 524        err = nfp_flower_metadata_init(app);
 525        if (err)
 526                goto err_free_app_priv;
 527
 528        /* Extract the extra features supported by the firmware. */
 529        features = nfp_rtsym_read_le(app->pf->rtbl,
 530                                     "_abi_flower_extra_features", &err);
 531        if (err)
 532                app_priv->flower_ext_feats = 0;
 533        else
 534                app_priv->flower_ext_feats = features;
 535
 536        return 0;
 537
 538err_free_app_priv:
 539        vfree(app->priv);
 540        return err;
 541}
 542
 543static void nfp_flower_clean(struct nfp_app *app)
 544{
 545        struct nfp_flower_priv *app_priv = app->priv;
 546
 547        skb_queue_purge(&app_priv->cmsg_skbs);
 548        flush_work(&app_priv->cmsg_work);
 549
 550        nfp_flower_metadata_cleanup(app);
 551        vfree(app->priv);
 552        app->priv = NULL;
 553}
 554
 555static int nfp_flower_start(struct nfp_app *app)
 556{
 557        return nfp_tunnel_config_start(app);
 558}
 559
 560static void nfp_flower_stop(struct nfp_app *app)
 561{
 562        nfp_tunnel_config_stop(app);
 563}
 564
 565const struct nfp_app_type app_flower = {
 566        .id             = NFP_APP_FLOWER_NIC,
 567        .name           = "flower",
 568
 569        .ctrl_cap_mask  = ~0U,
 570        .ctrl_has_meta  = true,
 571
 572        .extra_cap      = nfp_flower_extra_cap,
 573
 574        .init           = nfp_flower_init,
 575        .clean          = nfp_flower_clean,
 576
 577        .vnic_alloc     = nfp_flower_vnic_alloc,
 578        .vnic_init      = nfp_flower_vnic_init,
 579        .vnic_clean     = nfp_flower_vnic_clean,
 580
 581        .repr_init      = nfp_flower_repr_netdev_init,
 582        .repr_preclean  = nfp_flower_repr_netdev_preclean,
 583        .repr_clean     = nfp_flower_repr_netdev_clean,
 584
 585        .repr_open      = nfp_flower_repr_netdev_open,
 586        .repr_stop      = nfp_flower_repr_netdev_stop,
 587
 588        .start          = nfp_flower_start,
 589        .stop           = nfp_flower_stop,
 590
 591        .ctrl_msg_rx    = nfp_flower_cmsg_rx,
 592
 593        .sriov_enable   = nfp_flower_sriov_enable,
 594        .sriov_disable  = nfp_flower_sriov_disable,
 595
 596        .eswitch_mode_get  = eswitch_mode_get,
 597        .repr_get       = nfp_flower_repr_get,
 598
 599        .setup_tc       = nfp_flower_setup_tc,
 600};
 601