| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* -*- linux-c -*- |
|---|
| 2 | 3 | * INET 802.1Q VLAN |
|---|
| 3 | 4 | * Ethernet-type device handling. |
|---|
| .. | .. |
|---|
| 12 | 13 | * Oct 20, 2001: Ard van Breeman: |
|---|
| 13 | 14 | * - Fix MC-list, finally. |
|---|
| 14 | 15 | * - Flush MC-list on VLAN destroy. |
|---|
| 15 | | - * |
|---|
| 16 | | - * |
|---|
| 17 | | - * This program is free software; you can redistribute it and/or |
|---|
| 18 | | - * modify it under the terms of the GNU General Public License |
|---|
| 19 | | - * as published by the Free Software Foundation; either version |
|---|
| 20 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 21 | 16 | */ |
|---|
| 22 | 17 | |
|---|
| 23 | 18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| .. | .. |
|---|
| 31 | 26 | #include <linux/ethtool.h> |
|---|
| 32 | 27 | #include <linux/phy.h> |
|---|
| 33 | 28 | #include <net/arp.h> |
|---|
| 34 | | -#include <net/switchdev.h> |
|---|
| 35 | 29 | |
|---|
| 36 | 30 | #include "vlan.h" |
|---|
| 37 | 31 | #include "vlanproc.h" |
|---|
| .. | .. |
|---|
| 94 | 88 | static inline netdev_tx_t vlan_netpoll_send_skb(struct vlan_dev_priv *vlan, struct sk_buff *skb) |
|---|
| 95 | 89 | { |
|---|
| 96 | 90 | #ifdef CONFIG_NET_POLL_CONTROLLER |
|---|
| 97 | | - if (vlan->netpoll) |
|---|
| 98 | | - netpoll_send_skb(vlan->netpoll, skb); |
|---|
| 91 | + return netpoll_send_skb(vlan->netpoll, skb); |
|---|
| 99 | 92 | #else |
|---|
| 100 | 93 | BUG(); |
|---|
| 101 | | -#endif |
|---|
| 102 | 94 | return NETDEV_TX_OK; |
|---|
| 95 | +#endif |
|---|
| 103 | 96 | } |
|---|
| 104 | 97 | |
|---|
| 105 | 98 | static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, |
|---|
| .. | .. |
|---|
| 224 | 217 | u32 old_flags = vlan->flags; |
|---|
| 225 | 218 | |
|---|
| 226 | 219 | if (mask & ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP | |
|---|
| 227 | | - VLAN_FLAG_LOOSE_BINDING | VLAN_FLAG_MVRP)) |
|---|
| 220 | + VLAN_FLAG_LOOSE_BINDING | VLAN_FLAG_MVRP | |
|---|
| 221 | + VLAN_FLAG_BRIDGE_BINDING)) |
|---|
| 228 | 222 | return -EINVAL; |
|---|
| 229 | 223 | |
|---|
| 230 | 224 | vlan->flags = (old_flags & ~mask) | (flags & mask); |
|---|
| .. | .. |
|---|
| 297 | 291 | if (vlan->flags & VLAN_FLAG_MVRP) |
|---|
| 298 | 292 | vlan_mvrp_request_join(dev); |
|---|
| 299 | 293 | |
|---|
| 300 | | - if (netif_carrier_ok(real_dev)) |
|---|
| 294 | + if (netif_carrier_ok(real_dev) && |
|---|
| 295 | + !(vlan->flags & VLAN_FLAG_BRIDGE_BINDING)) |
|---|
| 301 | 296 | netif_carrier_on(dev); |
|---|
| 302 | 297 | return 0; |
|---|
| 303 | 298 | |
|---|
| .. | .. |
|---|
| 327 | 322 | if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr)) |
|---|
| 328 | 323 | dev_uc_del(real_dev, dev->dev_addr); |
|---|
| 329 | 324 | |
|---|
| 330 | | - netif_carrier_off(dev); |
|---|
| 325 | + if (!(vlan->flags & VLAN_FLAG_BRIDGE_BINDING)) |
|---|
| 326 | + netif_carrier_off(dev); |
|---|
| 331 | 327 | return 0; |
|---|
| 332 | 328 | } |
|---|
| 333 | 329 | |
|---|
| .. | .. |
|---|
| 371 | 367 | case SIOCSHWTSTAMP: |
|---|
| 372 | 368 | if (!net_eq(dev_net(dev), &init_net)) |
|---|
| 373 | 369 | break; |
|---|
| 370 | + fallthrough; |
|---|
| 374 | 371 | case SIOCGMIIPHY: |
|---|
| 375 | 372 | case SIOCGMIIREG: |
|---|
| 376 | 373 | case SIOCSMIIREG: |
|---|
| .. | .. |
|---|
| 446 | 443 | return rc; |
|---|
| 447 | 444 | } |
|---|
| 448 | 445 | |
|---|
| 449 | | -static int vlan_dev_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type) |
|---|
| 450 | | -{ |
|---|
| 451 | | - struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; |
|---|
| 452 | | - const struct net_device_ops *ops = real_dev->netdev_ops; |
|---|
| 453 | | - int rc = -EINVAL; |
|---|
| 454 | | - |
|---|
| 455 | | - if (ops->ndo_fcoe_get_wwn) |
|---|
| 456 | | - rc = ops->ndo_fcoe_get_wwn(real_dev, wwn, type); |
|---|
| 457 | | - return rc; |
|---|
| 458 | | -} |
|---|
| 459 | | - |
|---|
| 460 | 446 | static int vlan_dev_fcoe_ddp_target(struct net_device *dev, u16 xid, |
|---|
| 461 | 447 | struct scatterlist *sgl, unsigned int sgc) |
|---|
| 462 | 448 | { |
|---|
| .. | .. |
|---|
| 467 | 453 | if (ops->ndo_fcoe_ddp_target) |
|---|
| 468 | 454 | rc = ops->ndo_fcoe_ddp_target(real_dev, xid, sgl, sgc); |
|---|
| 469 | 455 | |
|---|
| 456 | + return rc; |
|---|
| 457 | +} |
|---|
| 458 | +#endif |
|---|
| 459 | + |
|---|
| 460 | +#ifdef NETDEV_FCOE_WWNN |
|---|
| 461 | +static int vlan_dev_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type) |
|---|
| 462 | +{ |
|---|
| 463 | + struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; |
|---|
| 464 | + const struct net_device_ops *ops = real_dev->netdev_ops; |
|---|
| 465 | + int rc = -EINVAL; |
|---|
| 466 | + |
|---|
| 467 | + if (ops->ndo_fcoe_get_wwn) |
|---|
| 468 | + rc = ops->ndo_fcoe_get_wwn(real_dev, wwn, type); |
|---|
| 470 | 469 | return rc; |
|---|
| 471 | 470 | } |
|---|
| 472 | 471 | #endif |
|---|
| .. | .. |
|---|
| 499 | 498 | |
|---|
| 500 | 499 | static void vlan_dev_set_lockdep_one(struct net_device *dev, |
|---|
| 501 | 500 | struct netdev_queue *txq, |
|---|
| 502 | | - void *_subclass) |
|---|
| 501 | + void *unused) |
|---|
| 503 | 502 | { |
|---|
| 504 | | - lockdep_set_class_and_subclass(&txq->_xmit_lock, |
|---|
| 505 | | - &vlan_netdev_xmit_lock_key, |
|---|
| 506 | | - *(int *)_subclass); |
|---|
| 503 | + lockdep_set_class(&txq->_xmit_lock, &vlan_netdev_xmit_lock_key); |
|---|
| 507 | 504 | } |
|---|
| 508 | 505 | |
|---|
| 509 | | -static void vlan_dev_set_lockdep_class(struct net_device *dev, int subclass) |
|---|
| 506 | +static void vlan_dev_set_lockdep_class(struct net_device *dev) |
|---|
| 510 | 507 | { |
|---|
| 511 | | - lockdep_set_class_and_subclass(&dev->addr_list_lock, |
|---|
| 512 | | - &vlan_netdev_addr_lock_key, |
|---|
| 513 | | - subclass); |
|---|
| 514 | | - netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, &subclass); |
|---|
| 515 | | -} |
|---|
| 516 | | - |
|---|
| 517 | | -static int vlan_dev_get_lock_subclass(struct net_device *dev) |
|---|
| 518 | | -{ |
|---|
| 519 | | - return vlan_dev_priv(dev)->nest_level; |
|---|
| 508 | + lockdep_set_class(&dev->addr_list_lock, |
|---|
| 509 | + &vlan_netdev_addr_lock_key); |
|---|
| 510 | + netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, NULL); |
|---|
| 520 | 511 | } |
|---|
| 521 | 512 | |
|---|
| 522 | 513 | static const struct header_ops vlan_header_ops = { |
|---|
| .. | .. |
|---|
| 551 | 542 | |
|---|
| 552 | 543 | static int vlan_dev_init(struct net_device *dev) |
|---|
| 553 | 544 | { |
|---|
| 554 | | - struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; |
|---|
| 545 | + struct vlan_dev_priv *vlan = vlan_dev_priv(dev); |
|---|
| 546 | + struct net_device *real_dev = vlan->real_dev; |
|---|
| 555 | 547 | |
|---|
| 556 | 548 | netif_carrier_off(dev); |
|---|
| 557 | 549 | |
|---|
| .. | .. |
|---|
| 562 | 554 | (1<<__LINK_STATE_DORMANT))) | |
|---|
| 563 | 555 | (1<<__LINK_STATE_PRESENT); |
|---|
| 564 | 556 | |
|---|
| 557 | + if (vlan->flags & VLAN_FLAG_BRIDGE_BINDING) |
|---|
| 558 | + dev->state |= (1 << __LINK_STATE_NOCARRIER); |
|---|
| 559 | + |
|---|
| 565 | 560 | dev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG | |
|---|
| 566 | 561 | NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE | |
|---|
| 562 | + NETIF_F_GSO_ENCAP_ALL | |
|---|
| 567 | 563 | NETIF_F_HIGHDMA | NETIF_F_SCTP_CRC | |
|---|
| 568 | 564 | NETIF_F_ALL_FCOE; |
|---|
| 569 | 565 | |
|---|
| .. | .. |
|---|
| 574 | 570 | netdev_warn(real_dev, "VLAN features are set incorrectly. Q-in-Q configurations may not work correctly.\n"); |
|---|
| 575 | 571 | |
|---|
| 576 | 572 | dev->vlan_features = real_dev->vlan_features & ~NETIF_F_ALL_FCOE; |
|---|
| 573 | + dev->hw_enc_features = vlan_tnl_features(real_dev); |
|---|
| 574 | + dev->mpls_features = real_dev->mpls_features; |
|---|
| 577 | 575 | |
|---|
| 578 | 576 | /* ipv6 shared card related stuff */ |
|---|
| 579 | 577 | dev->dev_id = real_dev->dev_id; |
|---|
| .. | .. |
|---|
| 590 | 588 | #endif |
|---|
| 591 | 589 | |
|---|
| 592 | 590 | dev->needed_headroom = real_dev->needed_headroom; |
|---|
| 593 | | - if (vlan_hw_offload_capable(real_dev->features, |
|---|
| 594 | | - vlan_dev_priv(dev)->vlan_proto)) { |
|---|
| 591 | + if (vlan_hw_offload_capable(real_dev->features, vlan->vlan_proto)) { |
|---|
| 595 | 592 | dev->header_ops = &vlan_passthru_header_ops; |
|---|
| 596 | 593 | dev->hard_header_len = real_dev->hard_header_len; |
|---|
| 597 | 594 | } else { |
|---|
| .. | .. |
|---|
| 603 | 600 | |
|---|
| 604 | 601 | SET_NETDEV_DEVTYPE(dev, &vlan_type); |
|---|
| 605 | 602 | |
|---|
| 606 | | - vlan_dev_set_lockdep_class(dev, vlan_dev_get_lock_subclass(dev)); |
|---|
| 603 | + vlan_dev_set_lockdep_class(dev); |
|---|
| 607 | 604 | |
|---|
| 608 | | - vlan_dev_priv(dev)->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); |
|---|
| 609 | | - if (!vlan_dev_priv(dev)->vlan_pcpu_stats) |
|---|
| 605 | + vlan->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); |
|---|
| 606 | + if (!vlan->vlan_pcpu_stats) |
|---|
| 610 | 607 | return -ENOMEM; |
|---|
| 608 | + |
|---|
| 609 | + /* Get vlan's reference to real_dev */ |
|---|
| 610 | + dev_hold(real_dev); |
|---|
| 611 | 611 | |
|---|
| 612 | 612 | return 0; |
|---|
| 613 | 613 | } |
|---|
| .. | .. |
|---|
| 673 | 673 | const struct ethtool_ops *ops = vlan->real_dev->ethtool_ops; |
|---|
| 674 | 674 | struct phy_device *phydev = vlan->real_dev->phydev; |
|---|
| 675 | 675 | |
|---|
| 676 | | - if (phydev && phydev->drv && phydev->drv->ts_info) { |
|---|
| 677 | | - return phydev->drv->ts_info(phydev, info); |
|---|
| 676 | + if (phy_has_tsinfo(phydev)) { |
|---|
| 677 | + return phy_ts_info(phydev, info); |
|---|
| 678 | 678 | } else if (ops->get_ts_info) { |
|---|
| 679 | 679 | return ops->get_ts_info(vlan->real_dev, info); |
|---|
| 680 | 680 | } else { |
|---|
| .. | .. |
|---|
| 759 | 759 | return; |
|---|
| 760 | 760 | |
|---|
| 761 | 761 | vlan->netpoll = NULL; |
|---|
| 762 | | - |
|---|
| 763 | | - __netpoll_free_async(netpoll); |
|---|
| 762 | + __netpoll_free(netpoll); |
|---|
| 764 | 763 | } |
|---|
| 765 | 764 | #endif /* CONFIG_NET_POLL_CONTROLLER */ |
|---|
| 766 | 765 | |
|---|
| .. | .. |
|---|
| 797 | 796 | .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done, |
|---|
| 798 | 797 | .ndo_fcoe_enable = vlan_dev_fcoe_enable, |
|---|
| 799 | 798 | .ndo_fcoe_disable = vlan_dev_fcoe_disable, |
|---|
| 800 | | - .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn, |
|---|
| 801 | 799 | .ndo_fcoe_ddp_target = vlan_dev_fcoe_ddp_target, |
|---|
| 800 | +#endif |
|---|
| 801 | +#ifdef NETDEV_FCOE_WWNN |
|---|
| 802 | + .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn, |
|---|
| 802 | 803 | #endif |
|---|
| 803 | 804 | #ifdef CONFIG_NET_POLL_CONTROLLER |
|---|
| 804 | 805 | .ndo_poll_controller = vlan_dev_poll_controller, |
|---|
| .. | .. |
|---|
| 806 | 807 | .ndo_netpoll_cleanup = vlan_dev_netpoll_cleanup, |
|---|
| 807 | 808 | #endif |
|---|
| 808 | 809 | .ndo_fix_features = vlan_dev_fix_features, |
|---|
| 809 | | - .ndo_get_lock_subclass = vlan_dev_get_lock_subclass, |
|---|
| 810 | 810 | .ndo_get_iflink = vlan_dev_get_iflink, |
|---|
| 811 | 811 | }; |
|---|
| 812 | 812 | |
|---|
| .. | .. |
|---|
| 816 | 816 | |
|---|
| 817 | 817 | free_percpu(vlan->vlan_pcpu_stats); |
|---|
| 818 | 818 | vlan->vlan_pcpu_stats = NULL; |
|---|
| 819 | + |
|---|
| 820 | + /* Get rid of the vlan's reference to real_dev */ |
|---|
| 821 | + dev_put(vlan->real_dev); |
|---|
| 819 | 822 | } |
|---|
| 820 | 823 | |
|---|
| 821 | 824 | void vlan_setup(struct net_device *dev) |
|---|