1. 20 8月, 2021 3 次提交
    • V
      net: mscc: ocelot: transmit the "native VLAN" error via extack · 01af940e
      Vladimir Oltean 提交于
      We need to reject some more configurations in future patches, convert
      the existing one to netlink extack.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      01af940e
    • V
      net: mscc: ocelot: allow probing to continue with ports that fail to register · 5c8bb71d
      Vladimir Oltean 提交于
      The existing ocelot device trees, like ocelot_pcb123.dts for example,
      have SERDES ports (ports 4 and higher) that do not have status = "disabled";
      but on the other hand do not have a phy-handle or a fixed-link either.
      
      So from the perspective of phylink, they have broken DT bindings.
      
      Since the blamed commit, probing for the entire switch will fail when
      such a device tree binding is encountered on a port. There used to be
      this piece of code which skipped ports without a phy-handle:
      
      	phy_node = of_parse_phandle(portnp, "phy-handle", 0);
      	if (!phy_node)
      		continue;
      
      but now it is gone.
      
      Anyway, fixed-link setups are a thing which should work out of the box
      with phylink, so it would not be in the best interest of the driver to
      add that check back.
      
      Instead, let's look at what other drivers do. Since commit 86f8b1c0
      ("net: dsa: Do not make user port errors fatal"), DSA continues after a
      switch port fails to register, and works only with the ports that
      succeeded.
      
      We can achieve the same behavior in ocelot by unregistering the devlink
      port for ports where ocelot_port_phylink_create() failed (called via
      ocelot_probe_port), and clear the bit in devlink_ports_registered for
      that port. This will make the next iteration reconsider the port that
      failed to probe as an unused port, and re-register a devlink port of
      type UNUSED for it. No other cleanup should need to be performed, since
      ocelot_probe_port() should be self-contained when it fails.
      
      Fixes: e6e12df6 ("net: mscc: ocelot: convert to phylink")
      Reported-and-tested-by: NHoratiu Vultur <horatiu.vultur@microchip.com>
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      5c8bb71d
    • H
      net: mscc: ocelot: be able to reuse a devlink_port after teardown · b5e33a15
      Horatiu Vultur 提交于
      There are cases where we would like to continue probing the switch even
      if one port has failed to probe. When that happens, we need to
      unregister a devlink_port of type DEVLINK_PORT_FLAVOUR_PHYSICAL and
      re-register it of type DEVLINK_PORT_FLAVOUR_UNUSED.
      
      This is fine, except when calling devlink_port_attrs_set on a structure
      on which devlink_port_register has been previously called, there is a
      WARN_ON in devlink_port_attrs_set that devlink_port->devlink must be
      NULL.
      
      So don't assume that the memory behind dlp is clean when calling
      ocelot_port_devlink_init, just zero-initialize it.
      Signed-off-by: NHoratiu Vultur <horatiu.vultur@microchip.com>
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      b5e33a15
  2. 19 8月, 2021 1 次提交
  3. 16 8月, 2021 2 次提交
    • V
      net: mscc: ocelot: convert to phylink · e6e12df6
      Vladimir Oltean 提交于
      The felix DSA driver, which is a wrapper over the same hardware class as
      ocelot, is integrated with phylink, but ocelot is using the plain PHY
      library. It makes sense to bring together the two implementations, which
      is what this patch achieves.
      
      This is a large patch and hard to break up, but it does the following:
      
      The existing ocelot_adjust_link writes some registers, and
      felix_phylink_mac_link_up writes some registers, some of them are
      common, but both functions write to some registers to which the other
      doesn't.
      
      The main reasons for this are:
      - Felix switches so far have used an NXP PCS so they had no need to
        write the PCS1G registers that ocelot_adjust_link writes
      - Felix switches have the MAC fixed at 1G, so some of the MAC speed
        changes actually break the link and must be avoided.
      
      The naming conventions for the functions introduced in this patch are:
      - vsc7514_phylink_{mac_config,validate} are specific to the Ocelot
        instantiations and placed in ocelot_net.c which is built only for the
        ocelot switchdev driver.
      - ocelot_phylink_mac_link_{up,down} are shared between the ocelot
        switchdev driver and the felix DSA driver (they are put in the common
        lib).
      
      One by one, the registers written by ocelot_adjust_link are:
      
      DEV_MAC_MODE_CFG - felix_phylink_mac_link_up had no need to write this
                         register since its out-of-reset value was fine and
                         did not need changing. The write is moved to the
                         common ocelot_phylink_mac_link_up and on felix it is
                         guarded by a quirk bit that makes the written value
                         identical with the out-of-reset one
      DEV_PORT_MISC - runtime invariant, was moved to vsc7514_phylink_mac_config
      PCS1G_MODE_CFG - same as above
      PCS1G_SD_CFG - same as above
      PCS1G_CFG - same as above
      PCS1G_ANEG_CFG - same as above
      PCS1G_LB_CFG - same as above
      DEV_MAC_ENA_CFG - both ocelot_adjust_link and ocelot_port_disable
                        touched this. felix_phylink_mac_link_{up,down} also
                        do. We go with what felix does and put it in
                        ocelot_phylink_mac_link_up.
      DEV_CLOCK_CFG - ocelot_adjust_link and felix_phylink_mac_link_up both
                      write this, but to different values. Move to the common
                      ocelot_phylink_mac_link_up and make sure via the quirk
                      that the old values are preserved for both.
      ANA_PFC_PFC_CFG - ocelot_adjust_link wrote this, felix_phylink_mac_link_up
                        did not. Runtime invariant, speed does not matter since
                        PFC is disabled via the RX_PFC_ENA bits which are cleared.
                        Move to vsc7514_phylink_mac_config.
      QSYS_SWITCH_PORT_MODE_PORT_ENA - both ocelot_adjust_link and
                                       felix_phylink_mac_link_{up,down} wrote
                                       this. Ocelot also wrote this register
                                       from ocelot_port_disable. Keep what
                                       felix did, move in ocelot_phylink_mac_link_{up,down}
                                       and delete ocelot_port_disable.
      ANA_POL_FLOWC - same as above
      SYS_MAC_FC_CFG - same as above, except slight behavior change. Whereas
                       ocelot always enabled RX and TX flow control, felix
                       listened to phylink (for the most part, at least - see
                       the 2500base-X comment).
      
      The registers which only felix_phylink_mac_link_up wrote are:
      
      SYS_PAUSE_CFG_PAUSE_ENA - this is why I am not sure that flow control
                                worked on ocelot. Not it should, since the
                                code is shared with felix where it does.
      ANA_PORT_PORT_CFG - this is a Frame Analyzer block register, phylink
                          should be the one touching them, deleted.
      
      Other changes:
      
      - The old phylib registration code was in mscc_ocelot_init_ports. It is
        hard to work with 2 levels of indentation already in, and with hard to
        follow teardown logic. The new phylink registration code was moved
        inside ocelot_probe_port(), right between alloc_etherdev() and
        register_netdev(). It could not be done before (=> outside of)
        ocelot_probe_port() because ocelot_probe_port() allocates the struct
        ocelot_port which we then use to assign ocelot_port->phy_mode to. It
        is more preferable to me to have all PHY handling logic inside the
        same function.
      - On the same topic: struct ocelot_port_private :: serdes is only used
        in ocelot_port_open to set the SERDES protocol to Ethernet. This is
        logically a runtime invariant and can be done just once, when the port
        registers with phylink. We therefore don't even need to keep the
        serdes reference inside struct ocelot_port_private, or to use the devm
        variant of of_phy_get().
      - Phylink needs a valid phy-mode for phylink_create() to succeed, and
        the existing device tree bindings in arch/mips/boot/dts/mscc/ocelot_pcb120.dts
        don't define one for the internal PHY ports. So we patch
        PHY_INTERFACE_MODE_NA into PHY_INTERFACE_MODE_INTERNAL.
      - There was a strategically placed:
      
      	switch (priv->phy_mode) {
      	case PHY_INTERFACE_MODE_NA:
      	        continue;
      
        which made the code skip the serdes initialization for the internal
        PHY ports. Frankly that is not all that obvious, so now we explicitly
        initialize the serdes under an "if" condition and not rely on code
        jumps, so everything is clearer.
      - There was a write of OCELOT_SPEED_1000 to DEV_CLOCK_CFG for QSGMII
        ports. Since that is in fact the default value for the register field
        DEV_CLOCK_CFG_LINK_SPEED, I can only guess the intention was to clear
        the adjacent fields, MAC_TX_RST and MAC_RX_RST, aka take the port out
        of reset, which does match the comment. I don't even want to know why
        this code is placed there, but if there is indeed an issue that all
        ports that share a QSGMII lane must all be up, then this logic is
        already buggy, since mscc_ocelot_init_ports iterates using
        for_each_available_child_of_node, so nobody prevents the user from
        putting a 'status = "disabled";' for some QSGMII ports which would
        break the driver's assumption.
        In any case, in the eventuality that I'm right, we would have yet
        another issue if ocelot_phylink_mac_link_down would reset those ports
        and that would be forbidden, so since the ocelot_adjust_link logic did
        not do that (maybe for a reason), add another quirk to preserve the
        old logic.
      
      The ocelot driver teardown goes through all ports in one fell swoop.
      When initialization of one port fails, the ocelot->ports[port] pointer
      for that is reset to NULL, and teardown is done only for non-NULL ports,
      so there is no reason to do partial teardowns, let the central
      mscc_ocelot_release_ports() do its job.
      
      Tested bind, unbind, rebind, link up, link down, speed change on mock-up
      hardware (modified the driver to probe on Felix VSC9959). Also
      regression tested the felix DSA driver. Could not test the Ocelot
      specific bits (PCS1G, SERDES, device tree bindings).
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      e6e12df6
    • V
      net: dsa: felix: stop calling ocelot_port_{enable,disable} · 46efe4ef
      Vladimir Oltean 提交于
      ocelot_port_enable touches ANA_PORT_PORT_CFG, which has the following
      fields:
      
      - LOCKED_PORTMOVE_CPU, LEARNDROP, LEARNCPU, LEARNAUTO, RECV_ENA, all of
        which are written with their hardware default values, also runtime
        invariants. So it makes no sense to write these during every .ndo_open.
      
      - PORTID_VAL: this field has an out-of-reset value of zero for all ports
        and must be initialized by software. Additionally, the
        ocelot_setup_logical_port_ids() code path sets up different logical
        port IDs for the ports in a hardware LAG, and we absolutely don't want
        .ndo_open to interfere there and reset those values.
      
      So in fact the write from ocelot_port_enable can better be moved to
      ocelot_init_port, and the .ndo_open hook deleted.
      
      ocelot_port_disable touches DEV_MAC_ENA_CFG and QSYS_SWITCH_PORT_MODE_PORT_ENA,
      in an attempt to undo what ocelot_adjust_link did. But since .ndo_stop
      does not get called each time the link falls (i.e. this isn't a
      substitute for .phylink_mac_link_down), felix already does better at
      this by writing those registers already in felix_phylink_mac_link_down.
      
      So keep ocelot_port_disable (for now, until ocelot is converted to
      phylink too), and just delete the felix call to it, which is not
      necessary.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      46efe4ef
  4. 14 8月, 2021 1 次提交
    • A
      ethernet: fix PTP_1588_CLOCK dependencies · e5f31552
      Arnd Bergmann 提交于
      The 'imply' keyword does not do what most people think it does, it only
      politely asks Kconfig to turn on another symbol, but does not prevent
      it from being disabled manually or built as a loadable module when the
      user is built-in. In the ICE driver, the latter now causes a link failure:
      
      aarch64-linux-ld: drivers/net/ethernet/intel/ice/ice_main.o: in function `ice_eth_ioctl':
      ice_main.c:(.text+0x13b0): undefined reference to `ice_ptp_get_ts_config'
      ice_main.c:(.text+0x13b0): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `ice_ptp_get_ts_config'
      aarch64-linux-ld: ice_main.c:(.text+0x13bc): undefined reference to `ice_ptp_set_ts_config'
      ice_main.c:(.text+0x13bc): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `ice_ptp_set_ts_config'
      aarch64-linux-ld: drivers/net/ethernet/intel/ice/ice_main.o: in function `ice_prepare_for_reset':
      ice_main.c:(.text+0x31fc): undefined reference to `ice_ptp_release'
      ice_main.c:(.text+0x31fc): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `ice_ptp_release'
      aarch64-linux-ld: drivers/net/ethernet/intel/ice/ice_main.o: in function `ice_rebuild':
      
      This is a recurring problem in many drivers, and we have discussed
      it several times befores, without reaching a consensus. I'm providing
      a link to the previous email thread for reference, which discusses
      some related problems.
      
      To solve the dependency issue better than the 'imply' keyword, introduce a
      separate Kconfig symbol "CONFIG_PTP_1588_CLOCK_OPTIONAL" that any driver
      can depend on if it is able to use PTP support when available, but works
      fine without it. Whenever CONFIG_PTP_1588_CLOCK=m, those drivers are
      then prevented from being built-in, the same way as with a 'depends on
      PTP_1588_CLOCK || !PTP_1588_CLOCK' dependency that does the same trick,
      but that can be rather confusing when you first see it.
      
      Since this should cover the dependencies correctly, the IS_REACHABLE()
      hack in the header is no longer needed now, and can be turned back
      into a normal IS_ENABLED() check. Any driver that gets the dependency
      wrong will now cause a link time failure rather than being unable to use
      PTP support when that is in a loadable module.
      
      However, the two recently added ptp_get_vclocks_index() and
      ptp_convert_timestamp() interfaces are only called from builtin code with
      ethtool and socket timestamps, so keep the current behavior by stubbing
      those out completely when PTP is in a loadable module. This should be
      addressed properly in a follow-up.
      
      As Richard suggested, we may want to actually turn PTP support into a
      'bool' option later on, preventing it from being a loadable module
      altogether, which would be one way to solve the problem with the ethtool
      interface.
      
      Fixes: 06c16d89 ("ice: register 1588 PTP clock device object for E810 devices")
      Link: https://lore.kernel.org/netdev/20210804121318.337276-1-arnd@kernel.org/
      Link: https://lore.kernel.org/netdev/CAK8P3a06enZOf=XyZ+zcAwBczv41UuCTz+=0FMf2gBz1_cOnZQ@mail.gmail.com/
      Link: https://lore.kernel.org/netdev/CAK8P3a3=eOxE-K25754+fB_-i_0BZzf9a9RfPTX3ppSwu9WZXw@mail.gmail.com/
      Link: https://lore.kernel.org/netdev/20210726084540.3282344-1-arnd@kernel.org/Acked-by: NShannon Nelson <snelson@pensando.io>
      Acked-by: NJacob Keller <jacob.e.keller@intel.com>
      Acked-by: NRichard Cochran <richardcochran@gmail.com>
      Reviewed-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NArnd Bergmann <arnd@arndb.de>
      Link: https://lore.kernel.org/r/20210812183509.1362782-1-arnd@kernel.orgSigned-off-by: NJakub Kicinski <kuba@kernel.org>
      e5f31552
  5. 12 8月, 2021 2 次提交
  6. 09 8月, 2021 1 次提交
    • L
      devlink: Set device as early as possible · 919d13a7
      Leon Romanovsky 提交于
      All kernel devlink implementations call to devlink_alloc() during
      initialization routine for specific device which is used later as
      a parent device for devlink_register().
      
      Such late device assignment causes to the situation which requires us to
      call to device_register() before setting other parameters, but that call
      opens devlink to the world and makes accessible for the netlink users.
      
      Any attempt to move devlink_register() to be the last call generates the
      following error due to access to the devlink->dev pointer.
      
      [    8.758862]  devlink_nl_param_fill+0x2e8/0xe50
      [    8.760305]  devlink_param_notify+0x6d/0x180
      [    8.760435]  __devlink_params_register+0x2f1/0x670
      [    8.760558]  devlink_params_register+0x1e/0x20
      
      The simple change of API to set devlink device in the devlink_alloc()
      instead of devlink_register() fixes all this above and ensures that
      prior to call to devlink_register() everything already set.
      Signed-off-by: NLeon Romanovsky <leonro@nvidia.com>
      Reviewed-by: NJiri Pirko <jiri@nvidia.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      919d13a7
  7. 28 7月, 2021 1 次提交
    • A
      dev_ioctl: split out ndo_eth_ioctl · a7605370
      Arnd Bergmann 提交于
      Most users of ndo_do_ioctl are ethernet drivers that implement
      the MII commands SIOCGMIIPHY/SIOCGMIIREG/SIOCSMIIREG, or hardware
      timestamping with SIOCSHWTSTAMP/SIOCGHWTSTAMP.
      
      Separate these from the few drivers that use ndo_do_ioctl to
      implement SIOCBOND, SIOCBR and SIOCWANDEV commands.
      
      This is a purely cosmetic change intended to help readers find
      their way through the implementation.
      
      Cc: Doug Ledford <dledford@redhat.com>
      Cc: Jason Gunthorpe <jgg@ziepe.ca>
      Cc: Jay Vosburgh <j.vosburgh@gmail.com>
      Cc: Veaceslav Falico <vfalico@gmail.com>
      Cc: Andy Gospodarek <andy@greyhouse.net>
      Cc: Andrew Lunn <andrew@lunn.ch>
      Cc: Vivien Didelot <vivien.didelot@gmail.com>
      Cc: Florian Fainelli <f.fainelli@gmail.com>
      Cc: Vladimir Oltean <olteanv@gmail.com>
      Cc: Leon Romanovsky <leon@kernel.org>
      Cc: linux-rdma@vger.kernel.org
      Signed-off-by: NArnd Bergmann <arnd@arndb.de>
      Acked-by: NJason Gunthorpe <jgg@nvidia.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      a7605370
  8. 23 7月, 2021 1 次提交
    • T
      net: bridge: switchdev: allow the TX data plane forwarding to be offloaded · 47211192
      Tobias Waldekranz 提交于
      Allow switchdevs to forward frames from the CPU in accordance with the
      bridge configuration in the same way as is done between bridge
      ports. This means that the bridge will only send a single skb towards
      one of the ports under the switchdev's control, and expects the driver
      to deliver the packet to all eligible ports in its domain.
      
      Primarily this improves the performance of multicast flows with
      multiple subscribers, as it allows the hardware to perform the frame
      replication.
      
      The basic flow between the driver and the bridge is as follows:
      
      - When joining a bridge port, the switchdev driver calls
        switchdev_bridge_port_offload() with tx_fwd_offload = true.
      
      - The bridge sends offloadable skbs to one of the ports under the
        switchdev's control using skb->offload_fwd_mark = true.
      
      - The switchdev driver checks the skb->offload_fwd_mark field and lets
        its FDB lookup select the destination port mask for this packet.
      
      v1->v2:
      - convert br_input_skb_cb::fwd_hwdoms to a plain unsigned long
      - introduce a static key "br_switchdev_fwd_offload_used" to minimize the
        impact of the newly introduced feature on all the setups which don't
        have hardware that can make use of it
      - introduce a check for nbp->flags & BR_FWD_OFFLOAD to optimize cache
        line access
      - reorder nbp_switchdev_frame_mark_accel() and br_handle_vlan() in
        __br_forward()
      - do not strip VLAN on egress if forwarding offload on VLAN-aware bridge
        is being used
      - propagate errors from .ndo_dfwd_add_station() if not EOPNOTSUPP
      
      v2->v3:
      - replace the solution based on .ndo_dfwd_add_station with a solution
        based on switchdev_bridge_port_offload
      - rename BR_FWD_OFFLOAD to BR_TX_FWD_OFFLOAD
      v3->v4: rebase
      v4->v5:
      - make sure the static key is decremented on bridge port unoffload
      - more function and variable renaming and comments for them:
        br_switchdev_fwd_offload_used to br_switchdev_tx_fwd_offload
        br_switchdev_accels_skb to br_switchdev_frame_uses_tx_fwd_offload
        nbp_switchdev_frame_mark_tx_fwd to nbp_switchdev_frame_mark_tx_fwd_to_hwdom
        nbp_switchdev_frame_mark_accel to nbp_switchdev_frame_mark_tx_fwd_offload
        fwd_accel to tx_fwd_offload
      Signed-off-by: NTobias Waldekranz <tobias@waldekranz.com>
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Reviewed-by: NFlorian Fainelli <f.fainelli@gmail.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      47211192
  9. 22 7月, 2021 2 次提交
    • V
      net: bridge: move the switchdev object replay helpers to "push" mode · 4e51bf44
      Vladimir Oltean 提交于
      Starting with commit 4f2673b3 ("net: bridge: add helper to replay
      port and host-joined mdb entries"), DSA has introduced some bridge
      helpers that replay switchdev events (FDB/MDB/VLAN additions and
      deletions) that can be lost by the switchdev drivers in a variety of
      circumstances:
      
      - an IP multicast group was host-joined on the bridge itself before any
        switchdev port joined the bridge, leading to the host MDB entries
        missing in the hardware database.
      - during the bridge creation process, the MAC address of the bridge was
        added to the FDB as an entry pointing towards the bridge device
        itself, but with no switchdev ports being part of the bridge yet, this
        local FDB entry would remain unknown to the switchdev hardware
        database.
      - a VLAN/FDB/MDB was added to a bridge port that is a LAG interface,
        before any switchdev port joined that LAG, leading to the hardware
        database missing those entries.
      - a switchdev port left a LAG that is a bridge port, while the LAG
        remained part of the bridge, and all FDB/MDB/VLAN entries remained
        installed in the hardware database of the switchdev port.
      
      Also, since commit 0d2cfbd4 ("net: bridge: ignore switchdev events
      for LAG ports which didn't request replay"), DSA introduced a method,
      based on a const void *ctx, to ensure that two switchdev ports under the
      same LAG that is a bridge port do not see the same MDB/VLAN entry being
      replayed twice by the bridge, once for every bridge port that joins the
      LAG.
      
      With so many ordering corner cases being possible, it seems unreasonable
      to expect a switchdev driver writer to get it right from the first try.
      Therefore, now that DSA has experimented with the bridge replay helpers
      for a little bit, we can move the code to the bridge driver where it is
      more readily available to all switchdev drivers.
      
      To convert the switchdev object replay helpers from "pull mode" (where
      the driver asks for them) to a "push mode" (where the bridge offers them
      automatically), the biggest problem is that the bridge needs to be aware
      when a switchdev port joins and leaves, even when the switchdev is only
      indirectly a bridge port (for example when the bridge port is a LAG
      upper of the switchdev).
      
      Luckily, we already have a hook for that, in the form of the newly
      introduced switchdev_bridge_port_offload() and
      switchdev_bridge_port_unoffload() calls. These offer a natural place for
      hooking the object addition and deletion replays.
      
      Extend the above 2 functions with:
      - pointers to the switchdev atomic notifier (for FDB replays) and the
        blocking notifier (for MDB and VLAN replays).
      - the "const void *ctx" argument required for drivers to be able to
        disambiguate between which port is targeted, when multiple ports are
        lowers of the same LAG that is a bridge port. Most of the drivers pass
        NULL to this argument, except the ones that support LAG offload and have
        the proper context check already in place in the switchdev blocking
        notifier handler.
      
      Also unexport the replay helpers, since nobody except the bridge calls
      them directly now.
      
      Note that:
      (a) we abuse the terminology slightly, because FDB entries are not
          "switchdev objects", but we count them as objects nonetheless.
          With no direct way to prove it, I think they are not modeled as
          switchdev objects because those can only be installed by the bridge
          to the hardware (as opposed to FDB entries which can be propagated
          in the other direction too). This is merely an abuse of terms, FDB
          entries are replayed too, despite not being objects.
      (b) the bridge does not attempt to sync port attributes to newly joined
          ports, just the countable stuff (the objects). The reason for this
          is simple: no universal and symmetric way to sync and unsync them is
          known. For example, VLAN filtering: what to do on unsync, disable or
          leave it enabled? Similarly, STP state, ageing timer, etc etc. What
          a switchdev port does when it becomes standalone again is not really
          up to the bridge's competence, and the driver should deal with it.
          On the other hand, replaying deletions of switchdev objects can be
          seen a matter of cleanup and therefore be treated by the bridge,
          hence this patch.
      
      We make the replay helpers opt-in for drivers, because they might not
      bring immediate benefits for them:
      
      - nbp_vlan_init() is called _after_ netdev_master_upper_dev_link(),
        so br_vlan_replay() should not do anything for the new drivers on
        which we call it. The existing drivers where there was even a slight
        possibility for there to exist a VLAN on a bridge port before they
        join it are already guarded against this: mlxsw and prestera deny
        joining LAG interfaces that are members of a bridge.
      
      - br_fdb_replay() should now notify of local FDB entries, but I patched
        all drivers except DSA to ignore these new entries in commit
        2c4eca3e ("net: bridge: switchdev: include local flag in FDB
        notifications"). Driver authors can lift this restriction as they
        wish, and when they do, they can also opt into the FDB replay
        functionality.
      
      - br_mdb_replay() should fix a real issue which is described in commit
        4f2673b3 ("net: bridge: add helper to replay port and host-joined
        mdb entries"). However most drivers do not offload the
        SWITCHDEV_OBJ_ID_HOST_MDB to see this issue: only cpsw and am65_cpsw
        offload this switchdev object, and I don't completely understand the
        way in which they offload this switchdev object anyway. So I'll leave
        it up to these drivers' respective maintainers to opt into
        br_mdb_replay().
      
      So most of the drivers pass NULL notifier blocks for the replay helpers,
      except:
      - dpaa2-switch which was already acked/regression-tested with the
        helpers enabled (and there isn't much of a downside in having them)
      - ocelot which already had replay logic in "pull" mode
      - DSA which already had replay logic in "pull" mode
      
      An important observation is that the drivers which don't currently
      request bridge event replays don't even have the
      switchdev_bridge_port_{offload,unoffload} calls placed in proper places
      right now. This was done to avoid unnecessary rework for drivers which
      might never even add support for this. For driver writers who wish to
      add replay support, this can be used as a tentative placement guide:
      https://patchwork.kernel.org/project/netdevbpf/patch/20210720134655.892334-11-vladimir.oltean@nxp.com/
      
      Cc: Vadym Kochan <vkochan@marvell.com>
      Cc: Taras Chornyi <tchornyi@marvell.com>
      Cc: Ioana Ciornei <ioana.ciornei@nxp.com>
      Cc: Lars Povlsen <lars.povlsen@microchip.com>
      Cc: Steen Hegelund <Steen.Hegelund@microchip.com>
      Cc: UNGLinuxDriver@microchip.com
      Cc: Claudiu Manoil <claudiu.manoil@nxp.com>
      Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
      Cc: Grygorii Strashko <grygorii.strashko@ti.com>
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Acked-by: Ioana Ciornei <ioana.ciornei@nxp.com> # dpaa2-switch
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      4e51bf44
    • V
      net: bridge: switchdev: let drivers inform which bridge ports are offloaded · 2f5dc00f
      Vladimir Oltean 提交于
      On reception of an skb, the bridge checks if it was marked as 'already
      forwarded in hardware' (checks if skb->offload_fwd_mark == 1), and if it
      is, it assigns the source hardware domain of that skb based on the
      hardware domain of the ingress port. Then during forwarding, it enforces
      that the egress port must have a different hardware domain than the
      ingress one (this is done in nbp_switchdev_allowed_egress).
      
      Non-switchdev drivers don't report any physical switch id (neither
      through devlink nor .ndo_get_port_parent_id), therefore the bridge
      assigns them a hardware domain of 0, and packets coming from them will
      always have skb->offload_fwd_mark = 0. So there aren't any restrictions.
      
      Problems appear due to the fact that DSA would like to perform software
      fallback for bonding and team interfaces that the physical switch cannot
      offload.
      
             +-- br0 ---+
            / /   |      \
           / /    |       \
          /  |    |      bond0
         /   |    |     /    \
       swp0 swp1 swp2 swp3 swp4
      
      There, it is desirable that the presence of swp3 and swp4 under a
      non-offloaded LAG does not preclude us from doing hardware bridging
      beteen swp0, swp1 and swp2. The bandwidth of the CPU is often times high
      enough that software bridging between {swp0,swp1,swp2} and bond0 is not
      impractical.
      
      But this creates an impossible paradox given the current way in which
      port hardware domains are assigned. When the driver receives a packet
      from swp0 (say, due to flooding), it must set skb->offload_fwd_mark to
      something.
      
      - If we set it to 0, then the bridge will forward it towards swp1, swp2
        and bond0. But the switch has already forwarded it towards swp1 and
        swp2 (not to bond0, remember, that isn't offloaded, so as far as the
        switch is concerned, ports swp3 and swp4 are not looking up the FDB,
        and the entire bond0 is a destination that is strictly behind the
        CPU). But we don't want duplicated traffic towards swp1 and swp2, so
        it's not ok to set skb->offload_fwd_mark = 0.
      
      - If we set it to 1, then the bridge will not forward the skb towards
        the ports with the same switchdev mark, i.e. not to swp1, swp2 and
        bond0. Towards swp1 and swp2 that's ok, but towards bond0? It should
        have forwarded the skb there.
      
      So the real issue is that bond0 will be assigned the same hardware
      domain as {swp0,swp1,swp2}, because the function that assigns hardware
      domains to bridge ports, nbp_switchdev_add(), recurses through bond0's
      lower interfaces until it finds something that implements devlink (calls
      dev_get_port_parent_id with bool recurse = true). This is a problem
      because the fact that bond0 can be offloaded by swp3 and swp4 in our
      example is merely an assumption.
      
      A solution is to give the bridge explicit hints as to what hardware
      domain it should use for each port.
      
      Currently, the bridging offload is very 'silent': a driver registers a
      netdevice notifier, which is put on the netns's notifier chain, and
      which sniffs around for NETDEV_CHANGEUPPER events where the upper is a
      bridge, and the lower is an interface it knows about (one registered by
      this driver, normally). Then, from within that notifier, it does a bunch
      of stuff behind the bridge's back, without the bridge necessarily
      knowing that there's somebody offloading that port. It looks like this:
      
           ip link set swp0 master br0
                        |
                        v
       br_add_if() calls netdev_master_upper_dev_link()
                        |
                        v
              call_netdevice_notifiers
                        |
                        v
             dsa_slave_netdevice_event
                        |
                        v
              oh, hey! it's for me!
                        |
                        v
                 .port_bridge_join
      
      What we do to solve the conundrum is to be less silent, and change the
      switchdev drivers to present themselves to the bridge. Something like this:
      
           ip link set swp0 master br0
                        |
                        v
       br_add_if() calls netdev_master_upper_dev_link()
                        |
                        v                    bridge: Aye! I'll use this
              call_netdevice_notifiers           ^  ppid as the
                        |                        |  hardware domain for
                        v                        |  this port, and zero
             dsa_slave_netdevice_event           |  if I got nothing.
                        |                        |
                        v                        |
              oh, hey! it's for me!              |
                        |                        |
                        v                        |
                 .port_bridge_join               |
                        |                        |
                        +------------------------+
                   switchdev_bridge_port_offload(swp0, swp0)
      
      Then stacked interfaces (like bond0 on top of swp3/swp4) would be
      treated differently in DSA, depending on whether we can or cannot
      offload them.
      
      The offload case:
      
          ip link set bond0 master br0
                        |
                        v
       br_add_if() calls netdev_master_upper_dev_link()
                        |
                        v                    bridge: Aye! I'll use this
              call_netdevice_notifiers           ^  ppid as the
                        |                        |  switchdev mark for
                        v                        |        bond0.
             dsa_slave_netdevice_event           | Coincidentally (or not),
                        |                        | bond0 and swp0, swp1, swp2
                        v                        | all have the same switchdev
              hmm, it's not quite for me,        | mark now, since the ASIC
               but my driver has already         | is able to forward towards
                 called .port_lag_join           | all these ports in hw.
                for it, because I have           |
            a port with dp->lag_dev == bond0.    |
                        |                        |
                        v                        |
                 .port_bridge_join               |
                 for swp3 and swp4               |
                        |                        |
                        +------------------------+
                  switchdev_bridge_port_offload(bond0, swp3)
                  switchdev_bridge_port_offload(bond0, swp4)
      
      And the non-offload case:
      
          ip link set bond0 master br0
                        |
                        v
       br_add_if() calls netdev_master_upper_dev_link()
                        |
                        v                    bridge waiting:
              call_netdevice_notifiers           ^  huh, switchdev_bridge_port_offload
                        |                        |  wasn't called, okay, I'll use a
                        v                        |  hwdom of zero for this one.
             dsa_slave_netdevice_event           :  Then packets received on swp0 will
                        |                        :  not be software-forwarded towards
                        v                        :  swp1, but they will towards bond0.
               it's not for me, but
             bond0 is an upper of swp3
            and swp4, but their dp->lag_dev
             is NULL because they couldn't
                  offload it.
      
      Basically we can draw the conclusion that the lowers of a bridge port
      can come and go, so depending on the configuration of lowers for a
      bridge port, it can dynamically toggle between offloaded and unoffloaded.
      Therefore, we need an equivalent switchdev_bridge_port_unoffload too.
      
      This patch changes the way any switchdev driver interacts with the
      bridge. From now on, everybody needs to call switchdev_bridge_port_offload
      and switchdev_bridge_port_unoffload, otherwise the bridge will treat the
      port as non-offloaded and allow software flooding to other ports from
      the same ASIC.
      
      Note that these functions lay the ground for a more complex handshake
      between switchdev drivers and the bridge in the future.
      
      For drivers that will request a replay of the switchdev objects when
      they offload and unoffload a bridge port (DSA, dpaa2-switch, ocelot), we
      place the call to switchdev_bridge_port_unoffload() strategically inside
      the NETDEV_PRECHANGEUPPER notifier's code path, and not inside
      NETDEV_CHANGEUPPER. This is because the switchdev object replay helpers
      need the netdev adjacency lists to be valid, and that is only true in
      NETDEV_PRECHANGEUPPER.
      
      Cc: Vadym Kochan <vkochan@marvell.com>
      Cc: Taras Chornyi <tchornyi@marvell.com>
      Cc: Ioana Ciornei <ioana.ciornei@nxp.com>
      Cc: Lars Povlsen <lars.povlsen@microchip.com>
      Cc: Steen Hegelund <Steen.Hegelund@microchip.com>
      Cc: UNGLinuxDriver@microchip.com
      Cc: Claudiu Manoil <claudiu.manoil@nxp.com>
      Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
      Cc: Grygorii Strashko <grygorii.strashko@ti.com>
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Tested-by: Ioana Ciornei <ioana.ciornei@nxp.com> # dpaa2-switch: regression
      Acked-by: Ioana Ciornei <ioana.ciornei@nxp.com> # dpaa2-switch
      Tested-by: Horatiu Vultur <horatiu.vultur@microchip.com> # ocelot-switch
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      2f5dc00f
  10. 14 7月, 2021 1 次提交
  11. 29 6月, 2021 4 次提交
    • V
      net: bridge: allow the switchdev replay functions to be called for deletion · 7e8c1858
      Vladimir Oltean 提交于
      When a switchdev port leaves a LAG that is a bridge port, the switchdev
      objects and port attributes offloaded to that port are not removed:
      
      ip link add br0 type bridge
      ip link add bond0 type bond mode 802.3ad
      ip link set swp0 master bond0
      ip link set bond0 master br0
      bridge vlan add dev bond0 vid 100
      ip link set swp0 nomaster
      
      VLAN 100 will remain installed on swp0 despite it going into standalone
      mode, because as far as the bridge is concerned, nothing ever happened
      to its bridge port.
      
      Let's extend the bridge vlan, fdb and mdb replay functions to take a
      'bool adding' argument, and make DSA and ocelot call the replay
      functions with 'adding' as false from the switchdev unsync path, for the
      switch port that leaves the bridge.
      
      Note that this patch in itself does not salvage anything, because in the
      current pull mode of operation, DSA still needs to call the replay
      helpers with adding=false. This will be done in another patch.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Reviewed-by: NFlorian Fainelli <f.fainelli@gmail.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      7e8c1858
    • V
      net: bridge: ignore switchdev events for LAG ports which didn't request replay · 0d2cfbd4
      Vladimir Oltean 提交于
      There is a slight inconvenience in the switchdev replay helpers added
      recently, and this is when:
      
      ip link add br0 type bridge
      ip link add bond0 type bond
      ip link set bond0 master br0
      bridge vlan add dev bond0 vid 100
      ip link set swp0 master bond0
      ip link set swp1 master bond0
      
      Since the underlying driver (currently only DSA) asks for a replay of
      VLANs when swp0 and swp1 join the LAG because it is bridged, what will
      happen is that DSA will try to react twice on the VLAN event for swp0.
      This is not really a huge problem right now, because most drivers accept
      duplicates since the bridge itself does, but it will become a problem
      when we add support for replaying switchdev object deletions.
      
      Let's fix this by adding a blank void *ctx in the replay helpers, which
      will be passed on by the bridge in the switchdev notifications. If the
      context is NULL, everything is the same as before. But if the context is
      populated with a valid pointer, the underlying switchdev driver
      (currently DSA) can use the pointer to 'see through' the bridge port
      (which in the example above is bond0) and 'know' that the event is only
      for a particular physical port offloading that bridge port, and not for
      all of them.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Reviewed-by: NFlorian Fainelli <f.fainelli@gmail.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      0d2cfbd4
    • V
      net: switchdev: add a context void pointer to struct switchdev_notifier_info · 69bfac96
      Vladimir Oltean 提交于
      In the case where the driver asks for a replay of a certain type of
      event (port object or attribute) for a bridge port that is a LAG, it may
      do so because this port has just joined the LAG.
      
      But there might already be other switchdev ports in that LAG, and it is
      preferable that those preexisting switchdev ports do not act upon the
      replayed event.
      
      The solution is to add a context to switchdev events, which is NULL most
      of the time (when the bridge layer initiates the call) but which can be
      set to a value controlled by the switchdev driver when a replay is
      requested. The driver can then check the context to figure out if all
      ports within the LAG should act upon the switchdev event, or just the
      ones that match the context.
      
      We have to modify all switchdev_handle_* helper functions as well as the
      prototypes in the drivers that use these helpers too, because these
      helpers hide the underlying struct switchdev_notifier_info from us and
      there is no way to retrieve the context otherwise.
      
      The context structure will be populated and used in later patches.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Reviewed-by: NFlorian Fainelli <f.fainelli@gmail.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      69bfac96
    • V
      net: ocelot: delete call to br_fdb_replay · 97558e88
      Vladimir Oltean 提交于
      Not using this driver, I did not realize it doesn't react to
      SWITCHDEV_FDB_{ADD,DEL}_TO_DEVICE notifications, but it implements just
      the bridge bypass operations (.ndo_fdb_{add,del}). So the call to
      br_fdb_replay just produces notifications that are ignored, delete it
      for now.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Reviewed-by: NFlorian Fainelli <f.fainelli@gmail.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      97558e88
  12. 09 6月, 2021 1 次提交
  13. 28 4月, 2021 3 次提交
  14. 07 4月, 2021 1 次提交
  15. 01 4月, 2021 1 次提交
  16. 25 3月, 2021 1 次提交
  17. 24 3月, 2021 2 次提交
    • V
      net: ocelot: replay switchdev events when joining bridge · e4bd44e8
      Vladimir Oltean 提交于
      The premise of this change is that the switchdev port attributes and
      objects offloaded by ocelot might have been missed when we are joining
      an already existing bridge port, such as a bonding interface.
      
      The patch pulls these switchdev attributes and objects from the bridge,
      on behalf of the 'bridge port' net device which might be either the
      ocelot switch interface, or the bonding upper interface.
      
      The ocelot_net.c belongs strictly to the switchdev ocelot driver, while
      ocelot.c is part of a library shared with the DSA felix driver.
      The ocelot_port_bridge_leave function (part of the common library) used
      to call ocelot_port_vlan_filtering(false), something which is not
      necessary for DSA, since the framework deals with that already there.
      So we move this function to ocelot_switchdev_unsync, which is specific
      to the switchdev driver.
      
      The code movement described above makes ocelot_port_bridge_leave no
      longer return an error code, so we change its type from int to void.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      e4bd44e8
    • V
      net: ocelot: call ocelot_netdevice_bridge_join when joining a bridged LAG · 81ef35e7
      Vladimir Oltean 提交于
      Similar to the DSA situation, ocelot supports LAG offload but treats
      this scenario improperly:
      
      ip link add br0 type bridge
      ip link add bond0 type bond
      ip link set bond0 master br0
      ip link set swp0 master bond0
      
      We do the same thing as we do there, which is to simulate a 'bridge join'
      on 'lag join', if we detect that the bonding upper has a bridge upper.
      
      Again, same as DSA, ocelot supports software fallback for LAG, and in
      that case, we should avoid calling ocelot_netdevice_changeupper.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      81ef35e7
  18. 19 3月, 2021 2 次提交
    • V
      net: ocelot: support multiple bridges · df291e54
      Vladimir Oltean 提交于
      The ocelot switches are a bit odd in that they do not have an STP state
      to put the ports into. Instead, the forwarding configuration is delayed
      from the typical port_bridge_join into stp_state_set, when the port enters
      the BR_STATE_FORWARDING state.
      
      I can only guess that the implementation of this quirk is the reason that
      led to the simplification of the driver such that only one bridge could
      be offloaded at a time.
      
      We can simplify the data structures somewhat, and introduce a per-port
      bridge device pointer and STP state, similar to how the LAG offload
      works now (there we have a per-port bonding device pointer and TX
      enabled state). This allows offloading multiple bridges with relative
      ease, while still keeping in place the quirk to delay the programming of
      the PGIDs.
      
      We actually need this change now because we need to remove the bogus
      restriction from ocelot_bridge_stp_state_set that ocelot->bridge_mask
      needs to contain BIT(port), otherwise that function is a no-op.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      df291e54
    • H
      net: ocelot: Fix deletetion of MRP entries from MAC table · d25fde64
      Horatiu Vultur 提交于
      When a MRP ring was deleted or disabled, the driver was iterating over
      the ports to detect if any other MPR rings exists and in case it didn't
      exist it would delete the MAC table entry. But the problem was that it
      used the last iterated port to delete the MAC table entry and this could
      be a NULL port.
      
      The fix consists of using the port on which the function was called.
      
      Fixes: 7c588c3e ("net: ocelot: Extend MRP")
      Reported-by: NDan Carpenter <dan.carpenter@oracle.com>
      Signed-off-by: NHoratiu Vultur <horatiu.vultur@microchip.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      d25fde64
  19. 17 3月, 2021 3 次提交
  20. 14 3月, 2021 1 次提交
  21. 11 3月, 2021 1 次提交
  22. 05 3月, 2021 1 次提交
  23. 27 2月, 2021 1 次提交
  24. 18 2月, 2021 1 次提交
  25. 17 2月, 2021 1 次提交
    • H
      net: mscc: ocelot: Add support for MRP · d8ea7ff3
      Horatiu Vultur 提交于
      Add basic support for MRP. The HW will just trap all MRP frames on the
      ring ports to CPU and allow the SW to process them. In this way it is
      possible to for this node to behave both as MRM and MRC.
      
      Current limitations are:
      - it doesn't support Interconnect roles.
      - it supports only a single ring.
      - the HW should be able to do forwarding of MRP Test frames so the SW
        will not need to do this. So it would be able to have the role MRC
        without SW support.
      Signed-off-by: NHoratiu Vultur <horatiu.vultur@microchip.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      d8ea7ff3
  26. 16 2月, 2021 1 次提交
    • V
      net: mscc: ocelot: avoid type promotion when calling ocelot_ifh_set_dest · 1f778d50
      Vladimir Oltean 提交于
      Smatch is confused by the fact that a 32-bit BIT(port) macro is passed
      as argument to the ocelot_ifh_set_dest function and warns:
      
      ocelot_xmit() warn: should '(((1))) << (dp->index)' be a 64 bit type?
      seville_xmit() warn: should '(((1))) << (dp->index)' be a 64 bit type?
      
      The destination port mask is copied into a 12-bit field of the packet,
      starting at bit offset 67 and ending at 56.
      
      So this DSA tagging protocol supports at most 12 bits, which is clearly
      less than 32. Attempting to send to a port number > 12 will cause the
      packing() call to truncate way before there will be 32-bit truncation
      due to type promotion of the BIT(port) argument towards u64.
      
      Therefore, smatch's fears that BIT(port) will do the wrong thing and
      cause unexpected truncation for "port" values >= 32 are unfounded.
      Nonetheless, let's silence the warning by explicitly passing an u64
      value to ocelot_ifh_set_dest, such that the compiler does not need to do
      a questionable type promotion.
      Reported-by: Nkernel test robot <lkp@intel.com>
      Reported-by: NDan Carpenter <dan.carpenter@oracle.com>
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      1f778d50