linux/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
<<
>>
Prefs
   1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
   2/* Copyright (C) 2017-2018 Netronome Systems, Inc. */
   3
   4#include <linux/etherdevice.h>
   5#include <linux/io-64-nonatomic-hi-lo.h>
   6#include <linux/lockdep.h>
   7#include <net/dst_metadata.h>
   8
   9#include "nfpcore/nfp_cpp.h"
  10#include "nfpcore/nfp_nsp.h"
  11#include "nfp_app.h"
  12#include "nfp_main.h"
  13#include "nfp_net.h"
  14#include "nfp_net_ctrl.h"
  15#include "nfp_net_repr.h"
  16#include "nfp_net_sriov.h"
  17#include "nfp_port.h"
  18
  19struct net_device *
  20nfp_repr_get_locked(struct nfp_app *app, struct nfp_reprs *set, unsigned int id)
  21{
  22        return rcu_dereference_protected(set->reprs[id],
  23                                         lockdep_is_held(&app->pf->lock));
  24}
  25
  26static void
  27nfp_repr_inc_tx_stats(struct net_device *netdev, unsigned int len,
  28                      int tx_status)
  29{
  30        struct nfp_repr *repr = netdev_priv(netdev);
  31        struct nfp_repr_pcpu_stats *stats;
  32
  33        if (unlikely(tx_status != NET_XMIT_SUCCESS &&
  34                     tx_status != NET_XMIT_CN)) {
  35                this_cpu_inc(repr->stats->tx_drops);
  36                return;
  37        }
  38
  39        stats = this_cpu_ptr(repr->stats);
  40        u64_stats_update_begin(&stats->syncp);
  41        stats->tx_packets++;
  42        stats->tx_bytes += len;
  43        u64_stats_update_end(&stats->syncp);
  44}
  45
  46void nfp_repr_inc_rx_stats(struct net_device *netdev, unsigned int len)
  47{
  48        struct nfp_repr *repr = netdev_priv(netdev);
  49        struct nfp_repr_pcpu_stats *stats;
  50
  51        stats = this_cpu_ptr(repr->stats);
  52        u64_stats_update_begin(&stats->syncp);
  53        stats->rx_packets++;
  54        stats->rx_bytes += len;
  55        u64_stats_update_end(&stats->syncp);
  56}
  57
  58static void
  59nfp_repr_phy_port_get_stats64(struct nfp_port *port,
  60                              struct rtnl_link_stats64 *stats)
  61{
  62        u8 __iomem *mem = port->eth_stats;
  63
  64        stats->tx_packets = readq(mem + NFP_MAC_STATS_TX_FRAMES_TRANSMITTED_OK);
  65        stats->tx_bytes = readq(mem + NFP_MAC_STATS_TX_OUT_OCTETS);
  66        stats->tx_dropped = readq(mem + NFP_MAC_STATS_TX_OUT_ERRORS);
  67
  68        stats->rx_packets = readq(mem + NFP_MAC_STATS_RX_FRAMES_RECEIVED_OK);
  69        stats->rx_bytes = readq(mem + NFP_MAC_STATS_RX_IN_OCTETS);
  70        stats->rx_dropped = readq(mem + NFP_MAC_STATS_RX_IN_ERRORS);
  71}
  72
  73static void
  74nfp_repr_vnic_get_stats64(struct nfp_port *port,
  75                          struct rtnl_link_stats64 *stats)
  76{
  77        /* TX and RX stats are flipped as we are returning the stats as seen
  78         * at the switch port corresponding to the VF.
  79         */
  80        stats->tx_packets = readq(port->vnic + NFP_NET_CFG_STATS_RX_FRAMES);
  81        stats->tx_bytes = readq(port->vnic + NFP_NET_CFG_STATS_RX_OCTETS);
  82        stats->tx_dropped = readq(port->vnic + NFP_NET_CFG_STATS_RX_DISCARDS);
  83
  84        stats->rx_packets = readq(port->vnic + NFP_NET_CFG_STATS_TX_FRAMES);
  85        stats->rx_bytes = readq(port->vnic + NFP_NET_CFG_STATS_TX_OCTETS);
  86        stats->rx_dropped = readq(port->vnic + NFP_NET_CFG_STATS_TX_DISCARDS);
  87}
  88
  89static void
  90nfp_repr_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
  91{
  92        struct nfp_repr *repr = netdev_priv(netdev);
  93
  94        if (WARN_ON(!repr->port))
  95                return;
  96
  97        switch (repr->port->type) {
  98        case NFP_PORT_PHYS_PORT:
  99                if (!__nfp_port_get_eth_port(repr->port))
 100                        break;
 101                nfp_repr_phy_port_get_stats64(repr->port, stats);
 102                break;
 103        case NFP_PORT_PF_PORT:
 104        case NFP_PORT_VF_PORT:
 105                nfp_repr_vnic_get_stats64(repr->port, stats);
 106        default:
 107                break;
 108        }
 109}
 110
 111static bool
 112nfp_repr_has_offload_stats(const struct net_device *dev, int attr_id)
 113{
 114        switch (attr_id) {
 115        case IFLA_OFFLOAD_XSTATS_CPU_HIT:
 116                return true;
 117        }
 118
 119        return false;
 120}
 121
 122static int
 123nfp_repr_get_host_stats64(const struct net_device *netdev,
 124                          struct rtnl_link_stats64 *stats)
 125{
 126        struct nfp_repr *repr = netdev_priv(netdev);
 127        int i;
 128
 129        for_each_possible_cpu(i) {
 130                u64 tbytes, tpkts, tdrops, rbytes, rpkts;
 131                struct nfp_repr_pcpu_stats *repr_stats;
 132                unsigned int start;
 133
 134                repr_stats = per_cpu_ptr(repr->stats, i);
 135                do {
 136                        start = u64_stats_fetch_begin_irq(&repr_stats->syncp);
 137                        tbytes = repr_stats->tx_bytes;
 138                        tpkts = repr_stats->tx_packets;
 139                        tdrops = repr_stats->tx_drops;
 140                        rbytes = repr_stats->rx_bytes;
 141                        rpkts = repr_stats->rx_packets;
 142                } while (u64_stats_fetch_retry_irq(&repr_stats->syncp, start));
 143
 144                stats->tx_bytes += tbytes;
 145                stats->tx_packets += tpkts;
 146                stats->tx_dropped += tdrops;
 147                stats->rx_bytes += rbytes;
 148                stats->rx_packets += rpkts;
 149        }
 150
 151        return 0;
 152}
 153
 154static int
 155nfp_repr_get_offload_stats(int attr_id, const struct net_device *dev,
 156                           void *stats)
 157{
 158        switch (attr_id) {
 159        case IFLA_OFFLOAD_XSTATS_CPU_HIT:
 160                return nfp_repr_get_host_stats64(dev, stats);
 161        }
 162
 163        return -EINVAL;
 164}
 165
 166static int nfp_repr_change_mtu(struct net_device *netdev, int new_mtu)
 167{
 168        struct nfp_repr *repr = netdev_priv(netdev);
 169        int err;
 170
 171        err = nfp_app_check_mtu(repr->app, netdev, new_mtu);
 172        if (err)
 173                return err;
 174
 175        err = nfp_app_repr_change_mtu(repr->app, netdev, new_mtu);
 176        if (err)
 177                return err;
 178
 179        netdev->mtu = new_mtu;
 180
 181        return 0;
 182}
 183
 184static netdev_tx_t nfp_repr_xmit(struct sk_buff *skb, struct net_device *netdev)
 185{
 186        struct nfp_repr *repr = netdev_priv(netdev);
 187        unsigned int len = skb->len;
 188        int ret;
 189
 190        skb_dst_drop(skb);
 191        dst_hold((struct dst_entry *)repr->dst);
 192        skb_dst_set(skb, (struct dst_entry *)repr->dst);
 193        skb->dev = repr->dst->u.port_info.lower_dev;
 194
 195        ret = dev_queue_xmit(skb);
 196        nfp_repr_inc_tx_stats(netdev, len, ret);
 197
 198        return NETDEV_TX_OK;
 199}
 200
 201static int nfp_repr_stop(struct net_device *netdev)
 202{
 203        struct nfp_repr *repr = netdev_priv(netdev);
 204        int err;
 205
 206        err = nfp_app_repr_stop(repr->app, repr);
 207        if (err)
 208                return err;
 209
 210        nfp_port_configure(netdev, false);
 211        return 0;
 212}
 213
 214static int nfp_repr_open(struct net_device *netdev)
 215{
 216        struct nfp_repr *repr = netdev_priv(netdev);
 217        int err;
 218
 219        err = nfp_port_configure(netdev, true);
 220        if (err)
 221                return err;
 222
 223        err = nfp_app_repr_open(repr->app, repr);
 224        if (err)
 225                goto err_port_disable;
 226
 227        return 0;
 228
 229err_port_disable:
 230        nfp_port_configure(netdev, false);
 231        return err;
 232}
 233
 234static netdev_features_t
 235nfp_repr_fix_features(struct net_device *netdev, netdev_features_t features)
 236{
 237        struct nfp_repr *repr = netdev_priv(netdev);
 238        netdev_features_t old_features = features;
 239        netdev_features_t lower_features;
 240        struct net_device *lower_dev;
 241
 242        lower_dev = repr->dst->u.port_info.lower_dev;
 243
 244        lower_features = lower_dev->features;
 245        if (lower_features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM))
 246                lower_features |= NETIF_F_HW_CSUM;
 247
 248        features = netdev_intersect_features(features, lower_features);
 249        features |= old_features & (NETIF_F_SOFT_FEATURES | NETIF_F_HW_TC);
 250        features |= NETIF_F_LLTX;
 251
 252        return features;
 253}
 254
 255const struct net_device_ops nfp_repr_netdev_ops = {
 256        .ndo_init               = nfp_app_ndo_init,
 257        .ndo_uninit             = nfp_app_ndo_uninit,
 258        .ndo_open               = nfp_repr_open,
 259        .ndo_stop               = nfp_repr_stop,
 260        .ndo_start_xmit         = nfp_repr_xmit,
 261        .ndo_change_mtu         = nfp_repr_change_mtu,
 262        .ndo_get_stats64        = nfp_repr_get_stats64,
 263        .ndo_has_offload_stats  = nfp_repr_has_offload_stats,
 264        .ndo_get_offload_stats  = nfp_repr_get_offload_stats,
 265        .ndo_get_phys_port_name = nfp_port_get_phys_port_name,
 266        .ndo_setup_tc           = nfp_port_setup_tc,
 267        .ndo_set_vf_mac         = nfp_app_set_vf_mac,
 268        .ndo_set_vf_vlan        = nfp_app_set_vf_vlan,
 269        .ndo_set_vf_spoofchk    = nfp_app_set_vf_spoofchk,
 270        .ndo_set_vf_trust       = nfp_app_set_vf_trust,
 271        .ndo_get_vf_config      = nfp_app_get_vf_config,
 272        .ndo_set_vf_link_state  = nfp_app_set_vf_link_state,
 273        .ndo_fix_features       = nfp_repr_fix_features,
 274        .ndo_set_features       = nfp_port_set_features,
 275        .ndo_set_mac_address    = eth_mac_addr,
 276        .ndo_get_port_parent_id = nfp_port_get_port_parent_id,
 277        .ndo_get_devlink_port   = nfp_devlink_get_devlink_port,
 278};
 279
 280void
 281nfp_repr_transfer_features(struct net_device *netdev, struct net_device *lower)
 282{
 283        struct nfp_repr *repr = netdev_priv(netdev);
 284
 285        if (repr->dst->u.port_info.lower_dev != lower)
 286                return;
 287
 288        netdev->gso_max_size = lower->gso_max_size;
 289        netdev->gso_max_segs = lower->gso_max_segs;
 290
 291        netdev_update_features(netdev);
 292}
 293
 294static void nfp_repr_clean(struct nfp_repr *repr)
 295{
 296        unregister_netdev(repr->netdev);
 297        nfp_app_repr_clean(repr->app, repr->netdev);
 298        dst_release((struct dst_entry *)repr->dst);
 299        nfp_port_free(repr->port);
 300}
 301
 302int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
 303                  u32 cmsg_port_id, struct nfp_port *port,
 304                  struct net_device *pf_netdev)
 305{
 306        struct nfp_repr *repr = netdev_priv(netdev);
 307        struct nfp_net *nn = netdev_priv(pf_netdev);
 308        u32 repr_cap = nn->tlv_caps.repr_cap;
 309        int err;
 310
 311        repr->port = port;
 312        repr->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, GFP_KERNEL);
 313        if (!repr->dst)
 314                return -ENOMEM;
 315        repr->dst->u.port_info.port_id = cmsg_port_id;
 316        repr->dst->u.port_info.lower_dev = pf_netdev;
 317
 318        netdev->netdev_ops = &nfp_repr_netdev_ops;
 319        netdev->ethtool_ops = &nfp_port_ethtool_ops;
 320
 321        netdev->max_mtu = pf_netdev->max_mtu;
 322
 323        /* Set features the lower device can support with representors */
 324        if (repr_cap & NFP_NET_CFG_CTRL_LIVE_ADDR)
 325                netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 326
 327        netdev->hw_features = NETIF_F_HIGHDMA;
 328        if (repr_cap & NFP_NET_CFG_CTRL_RXCSUM_ANY)
 329                netdev->hw_features |= NETIF_F_RXCSUM;
 330        if (repr_cap & NFP_NET_CFG_CTRL_TXCSUM)
 331                netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
 332        if (repr_cap & NFP_NET_CFG_CTRL_GATHER)
 333                netdev->hw_features |= NETIF_F_SG;
 334        if ((repr_cap & NFP_NET_CFG_CTRL_LSO && nn->fw_ver.major > 2) ||
 335            repr_cap & NFP_NET_CFG_CTRL_LSO2)
 336                netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
 337        if (repr_cap & NFP_NET_CFG_CTRL_RSS_ANY)
 338                netdev->hw_features |= NETIF_F_RXHASH;
 339        if (repr_cap & NFP_NET_CFG_CTRL_VXLAN) {
 340                if (repr_cap & NFP_NET_CFG_CTRL_LSO)
 341                        netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
 342        }
 343        if (repr_cap & NFP_NET_CFG_CTRL_NVGRE) {
 344                if (repr_cap & NFP_NET_CFG_CTRL_LSO)
 345                        netdev->hw_features |= NETIF_F_GSO_GRE;
 346        }
 347        if (repr_cap & (NFP_NET_CFG_CTRL_VXLAN | NFP_NET_CFG_CTRL_NVGRE))
 348                netdev->hw_enc_features = netdev->hw_features;
 349
 350        netdev->vlan_features = netdev->hw_features;
 351
 352        if (repr_cap & NFP_NET_CFG_CTRL_RXVLAN)
 353                netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
 354        if (repr_cap & NFP_NET_CFG_CTRL_TXVLAN) {
 355                if (repr_cap & NFP_NET_CFG_CTRL_LSO2)
 356                        netdev_warn(netdev, "Device advertises both TSO2 and TXVLAN. Refusing to enable TXVLAN.\n");
 357                else
 358                        netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX;
 359        }
 360        if (repr_cap & NFP_NET_CFG_CTRL_CTAG_FILTER)
 361                netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 362
 363        netdev->features = netdev->hw_features;
 364
 365        /* Advertise but disable TSO by default. */
 366        netdev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
 367        netdev->gso_max_segs = NFP_NET_LSO_MAX_SEGS;
 368
 369        netdev->priv_flags |= IFF_NO_QUEUE | IFF_DISABLE_NETPOLL;
 370        netdev->features |= NETIF_F_LLTX;
 371
 372        if (nfp_app_has_tc(app)) {
 373                netdev->features |= NETIF_F_HW_TC;
 374                netdev->hw_features |= NETIF_F_HW_TC;
 375        }
 376
 377        err = nfp_app_repr_init(app, netdev);
 378        if (err)
 379                goto err_clean;
 380
 381        err = register_netdev(netdev);
 382        if (err)
 383                goto err_repr_clean;
 384
 385        return 0;
 386
 387err_repr_clean:
 388        nfp_app_repr_clean(app, netdev);
 389err_clean:
 390        dst_release((struct dst_entry *)repr->dst);
 391        return err;
 392}
 393
 394static void __nfp_repr_free(struct nfp_repr *repr)
 395{
 396        free_percpu(repr->stats);
 397        free_netdev(repr->netdev);
 398}
 399
 400void nfp_repr_free(struct net_device *netdev)
 401{
 402        __nfp_repr_free(netdev_priv(netdev));
 403}
 404
 405struct net_device *
 406nfp_repr_alloc_mqs(struct nfp_app *app, unsigned int txqs, unsigned int rxqs)
 407{
 408        struct net_device *netdev;
 409        struct nfp_repr *repr;
 410
 411        netdev = alloc_etherdev_mqs(sizeof(*repr), txqs, rxqs);
 412        if (!netdev)
 413                return NULL;
 414
 415        netif_carrier_off(netdev);
 416
 417        repr = netdev_priv(netdev);
 418        repr->netdev = netdev;
 419        repr->app = app;
 420
 421        repr->stats = netdev_alloc_pcpu_stats(struct nfp_repr_pcpu_stats);
 422        if (!repr->stats)
 423                goto err_free_netdev;
 424
 425        return netdev;
 426
 427err_free_netdev:
 428        free_netdev(netdev);
 429        return NULL;
 430}
 431
 432void nfp_repr_clean_and_free(struct nfp_repr *repr)
 433{
 434        nfp_info(repr->app->cpp, "Destroying Representor(%s)\n",
 435                 repr->netdev->name);
 436        nfp_repr_clean(repr);
 437        __nfp_repr_free(repr);
 438}
 439
 440void nfp_reprs_clean_and_free(struct nfp_app *app, struct nfp_reprs *reprs)
 441{
 442        struct net_device *netdev;
 443        unsigned int i;
 444
 445        for (i = 0; i < reprs->num_reprs; i++) {
 446                netdev = nfp_repr_get_locked(app, reprs, i);
 447                if (netdev)
 448                        nfp_repr_clean_and_free(netdev_priv(netdev));
 449        }
 450
 451        kfree(reprs);
 452}
 453
 454void
 455nfp_reprs_clean_and_free_by_type(struct nfp_app *app, enum nfp_repr_type type)
 456{
 457        struct net_device *netdev;
 458        struct nfp_reprs *reprs;
 459        int i;
 460
 461        reprs = rcu_dereference_protected(app->reprs[type],
 462                                          lockdep_is_held(&app->pf->lock));
 463        if (!reprs)
 464                return;
 465
 466        /* Preclean must happen before we remove the reprs reference from the
 467         * app below.
 468         */
 469        for (i = 0; i < reprs->num_reprs; i++) {
 470                netdev = nfp_repr_get_locked(app, reprs, i);
 471                if (netdev)
 472                        nfp_app_repr_preclean(app, netdev);
 473        }
 474
 475        reprs = nfp_app_reprs_set(app, type, NULL);
 476
 477        synchronize_rcu();
 478        nfp_reprs_clean_and_free(app, reprs);
 479}
 480
 481struct nfp_reprs *nfp_reprs_alloc(unsigned int num_reprs)
 482{
 483        struct nfp_reprs *reprs;
 484
 485        reprs = kzalloc(sizeof(*reprs) +
 486                        num_reprs * sizeof(struct net_device *), GFP_KERNEL);
 487        if (!reprs)
 488                return NULL;
 489        reprs->num_reprs = num_reprs;
 490
 491        return reprs;
 492}
 493
 494int nfp_reprs_resync_phys_ports(struct nfp_app *app)
 495{
 496        struct net_device *netdev;
 497        struct nfp_reprs *reprs;
 498        struct nfp_repr *repr;
 499        int i;
 500
 501        reprs = nfp_reprs_get_locked(app, NFP_REPR_TYPE_PHYS_PORT);
 502        if (!reprs)
 503                return 0;
 504
 505        for (i = 0; i < reprs->num_reprs; i++) {
 506                netdev = nfp_repr_get_locked(app, reprs, i);
 507                if (!netdev)
 508                        continue;
 509
 510                repr = netdev_priv(netdev);
 511                if (repr->port->type != NFP_PORT_INVALID)
 512                        continue;
 513
 514                nfp_app_repr_preclean(app, netdev);
 515                rtnl_lock();
 516                rcu_assign_pointer(reprs->reprs[i], NULL);
 517                rtnl_unlock();
 518                synchronize_rcu();
 519                nfp_repr_clean(repr);
 520        }
 521
 522        return 0;
 523}
 524