| .. | .. |
|---|
| 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 | | - */ |
|---|
| 1 | +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
|---|
| 2 | +/* Copyright (C) 2017-2018 Netronome Systems, Inc. */ |
|---|
| 33 | 3 | |
|---|
| 34 | 4 | #include <linux/etherdevice.h> |
|---|
| 35 | 5 | #include <linux/io-64-nonatomic-hi-lo.h> |
|---|
| 36 | 6 | #include <linux/lockdep.h> |
|---|
| 37 | 7 | #include <net/dst_metadata.h> |
|---|
| 38 | | -#include <net/switchdev.h> |
|---|
| 39 | 8 | |
|---|
| 40 | 9 | #include "nfpcore/nfp_cpp.h" |
|---|
| 41 | 10 | #include "nfpcore/nfp_nsp.h" |
|---|
| 42 | 11 | #include "nfp_app.h" |
|---|
| 43 | 12 | #include "nfp_main.h" |
|---|
| 13 | +#include "nfp_net.h" |
|---|
| 44 | 14 | #include "nfp_net_ctrl.h" |
|---|
| 45 | 15 | #include "nfp_net_repr.h" |
|---|
| 46 | 16 | #include "nfp_net_sriov.h" |
|---|
| .. | .. |
|---|
| 261 | 231 | return err; |
|---|
| 262 | 232 | } |
|---|
| 263 | 233 | |
|---|
| 234 | +static netdev_features_t |
|---|
| 235 | +nfp_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 | + |
|---|
| 264 | 255 | const struct net_device_ops nfp_repr_netdev_ops = { |
|---|
| 265 | 256 | .ndo_init = nfp_app_ndo_init, |
|---|
| 266 | 257 | .ndo_uninit = nfp_app_ndo_uninit, |
|---|
| .. | .. |
|---|
| 276 | 267 | .ndo_set_vf_mac = nfp_app_set_vf_mac, |
|---|
| 277 | 268 | .ndo_set_vf_vlan = nfp_app_set_vf_vlan, |
|---|
| 278 | 269 | .ndo_set_vf_spoofchk = nfp_app_set_vf_spoofchk, |
|---|
| 270 | + .ndo_set_vf_trust = nfp_app_set_vf_trust, |
|---|
| 279 | 271 | .ndo_get_vf_config = nfp_app_get_vf_config, |
|---|
| 280 | 272 | .ndo_set_vf_link_state = nfp_app_set_vf_link_state, |
|---|
| 273 | + .ndo_fix_features = nfp_repr_fix_features, |
|---|
| 281 | 274 | .ndo_set_features = nfp_port_set_features, |
|---|
| 282 | 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, |
|---|
| 283 | 278 | }; |
|---|
| 279 | + |
|---|
| 280 | +void |
|---|
| 281 | +nfp_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 | +} |
|---|
| 284 | 293 | |
|---|
| 285 | 294 | static void nfp_repr_clean(struct nfp_repr *repr) |
|---|
| 286 | 295 | { |
|---|
| .. | .. |
|---|
| 291 | 300 | } |
|---|
| 292 | 301 | |
|---|
| 293 | 302 | static struct lock_class_key nfp_repr_netdev_xmit_lock_key; |
|---|
| 294 | | -static struct lock_class_key nfp_repr_netdev_addr_lock_key; |
|---|
| 295 | 303 | |
|---|
| 296 | 304 | static void nfp_repr_set_lockdep_class_one(struct net_device *dev, |
|---|
| 297 | 305 | struct netdev_queue *txq, |
|---|
| .. | .. |
|---|
| 302 | 310 | |
|---|
| 303 | 311 | static void nfp_repr_set_lockdep_class(struct net_device *dev) |
|---|
| 304 | 312 | { |
|---|
| 305 | | - lockdep_set_class(&dev->addr_list_lock, &nfp_repr_netdev_addr_lock_key); |
|---|
| 306 | 313 | netdev_for_each_tx_queue(dev, nfp_repr_set_lockdep_class_one, NULL); |
|---|
| 307 | 314 | } |
|---|
| 308 | 315 | |
|---|
| .. | .. |
|---|
| 311 | 318 | struct net_device *pf_netdev) |
|---|
| 312 | 319 | { |
|---|
| 313 | 320 | struct nfp_repr *repr = netdev_priv(netdev); |
|---|
| 321 | + struct nfp_net *nn = netdev_priv(pf_netdev); |
|---|
| 322 | + u32 repr_cap = nn->tlv_caps.repr_cap; |
|---|
| 314 | 323 | int err; |
|---|
| 315 | 324 | |
|---|
| 316 | 325 | nfp_repr_set_lockdep_class(netdev); |
|---|
| .. | .. |
|---|
| 327 | 336 | |
|---|
| 328 | 337 | netdev->max_mtu = pf_netdev->max_mtu; |
|---|
| 329 | 338 | |
|---|
| 330 | | - SWITCHDEV_SET_OPS(netdev, &nfp_port_switchdev_ops); |
|---|
| 339 | + /* Set features the lower device can support with representors */ |
|---|
| 340 | + if (repr_cap & NFP_NET_CFG_CTRL_LIVE_ADDR) |
|---|
| 341 | + netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE; |
|---|
| 331 | 342 | |
|---|
| 332 | | - netdev->priv_flags |= IFF_DISABLE_NETPOLL; |
|---|
| 343 | + netdev->hw_features = NETIF_F_HIGHDMA; |
|---|
| 344 | + if (repr_cap & NFP_NET_CFG_CTRL_RXCSUM_ANY) |
|---|
| 345 | + netdev->hw_features |= NETIF_F_RXCSUM; |
|---|
| 346 | + if (repr_cap & NFP_NET_CFG_CTRL_TXCSUM) |
|---|
| 347 | + netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; |
|---|
| 348 | + if (repr_cap & NFP_NET_CFG_CTRL_GATHER) |
|---|
| 349 | + netdev->hw_features |= NETIF_F_SG; |
|---|
| 350 | + if ((repr_cap & NFP_NET_CFG_CTRL_LSO && nn->fw_ver.major > 2) || |
|---|
| 351 | + repr_cap & NFP_NET_CFG_CTRL_LSO2) |
|---|
| 352 | + netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6; |
|---|
| 353 | + if (repr_cap & NFP_NET_CFG_CTRL_RSS_ANY) |
|---|
| 354 | + netdev->hw_features |= NETIF_F_RXHASH; |
|---|
| 355 | + if (repr_cap & NFP_NET_CFG_CTRL_VXLAN) { |
|---|
| 356 | + if (repr_cap & NFP_NET_CFG_CTRL_LSO) |
|---|
| 357 | + netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL; |
|---|
| 358 | + } |
|---|
| 359 | + if (repr_cap & NFP_NET_CFG_CTRL_NVGRE) { |
|---|
| 360 | + if (repr_cap & NFP_NET_CFG_CTRL_LSO) |
|---|
| 361 | + netdev->hw_features |= NETIF_F_GSO_GRE; |
|---|
| 362 | + } |
|---|
| 363 | + if (repr_cap & (NFP_NET_CFG_CTRL_VXLAN | NFP_NET_CFG_CTRL_NVGRE)) |
|---|
| 364 | + netdev->hw_enc_features = netdev->hw_features; |
|---|
| 365 | + |
|---|
| 366 | + netdev->vlan_features = netdev->hw_features; |
|---|
| 367 | + |
|---|
| 368 | + if (repr_cap & NFP_NET_CFG_CTRL_RXVLAN) |
|---|
| 369 | + netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX; |
|---|
| 370 | + if (repr_cap & NFP_NET_CFG_CTRL_TXVLAN) { |
|---|
| 371 | + if (repr_cap & NFP_NET_CFG_CTRL_LSO2) |
|---|
| 372 | + netdev_warn(netdev, "Device advertises both TSO2 and TXVLAN. Refusing to enable TXVLAN.\n"); |
|---|
| 373 | + else |
|---|
| 374 | + netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX; |
|---|
| 375 | + } |
|---|
| 376 | + if (repr_cap & NFP_NET_CFG_CTRL_CTAG_FILTER) |
|---|
| 377 | + netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER; |
|---|
| 378 | + |
|---|
| 379 | + netdev->features = netdev->hw_features; |
|---|
| 380 | + |
|---|
| 381 | + /* Advertise but disable TSO by default. */ |
|---|
| 382 | + netdev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); |
|---|
| 383 | + netdev->gso_max_segs = NFP_NET_LSO_MAX_SEGS; |
|---|
| 384 | + |
|---|
| 385 | + netdev->priv_flags |= IFF_NO_QUEUE | IFF_DISABLE_NETPOLL; |
|---|
| 386 | + netdev->features |= NETIF_F_LLTX; |
|---|
| 333 | 387 | |
|---|
| 334 | 388 | if (nfp_app_has_tc(app)) { |
|---|
| 335 | 389 | netdev->features |= NETIF_F_HW_TC; |
|---|
| .. | .. |
|---|
| 474 | 528 | continue; |
|---|
| 475 | 529 | |
|---|
| 476 | 530 | nfp_app_repr_preclean(app, netdev); |
|---|
| 531 | + rtnl_lock(); |
|---|
| 477 | 532 | rcu_assign_pointer(reprs->reprs[i], NULL); |
|---|
| 533 | + rtnl_unlock(); |
|---|
| 478 | 534 | synchronize_rcu(); |
|---|
| 479 | 535 | nfp_repr_clean(repr); |
|---|
| 480 | 536 | } |
|---|