.. | .. |
---|
| 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) |
---|