linux/net/dsa/port.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Handling of a single switch port
 *
 * Copyright (c) 2017 Savoir-faire Linux Inc.
 *	Vivien Didelot <[email protected]>
 */

#include <linux/if_bridge.h>
#include <linux/netdevice.h>
#include <linux/notifier.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>

#include "dsa.h"
#include "port.h"
#include "switch.h"
#include "tag_8021q.h"
#include "user.h"

/**
 * dsa_port_notify - Notify the switching fabric of changes to a port
 * @dp: port on which change occurred
 * @e: event, must be of type DSA_NOTIFIER_*
 * @v: event-specific value.
 *
 * Notify all switches in the DSA tree that this port's switch belongs to,
 * including this switch itself, of an event. Allows the other switches to
 * reconfigure themselves for cross-chip operations. Can also be used to
 * reconfigure ports without net_devices (CPU ports, DSA links) whenever
 * a user port's state changes.
 */
static int dsa_port_notify(const struct dsa_port *dp, unsigned long e, void *v)
{}

static void dsa_port_notify_bridge_fdb_flush(const struct dsa_port *dp, u16 vid)
{}

static void dsa_port_fast_age(const struct dsa_port *dp)
{}

static int dsa_port_vlan_fast_age(const struct dsa_port *dp, u16 vid)
{}

static int dsa_port_msti_fast_age(const struct dsa_port *dp, u16 msti)
{}

static bool dsa_port_can_configure_learning(struct dsa_port *dp)
{}

bool dsa_port_supports_hwtstamp(struct dsa_port *dp)
{}

int dsa_port_set_state(struct dsa_port *dp, u8 state, bool do_fast_age)
{}

static void dsa_port_set_state_now(struct dsa_port *dp, u8 state,
				   bool do_fast_age)
{}

int dsa_port_set_mst_state(struct dsa_port *dp,
			   const struct switchdev_mst_state *state,
			   struct netlink_ext_ack *extack)
{}

int dsa_port_enable_rt(struct dsa_port *dp, struct phy_device *phy)
{}

int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy)
{}

void dsa_port_disable_rt(struct dsa_port *dp)
{}

void dsa_port_disable(struct dsa_port *dp)
{}

static void dsa_port_reset_vlan_filtering(struct dsa_port *dp,
					  struct dsa_bridge bridge)
{}

static int dsa_port_inherit_brport_flags(struct dsa_port *dp,
					 struct netlink_ext_ack *extack)
{}

static void dsa_port_clear_brport_flags(struct dsa_port *dp)
{}

static int dsa_port_switchdev_sync_attrs(struct dsa_port *dp,
					 struct netlink_ext_ack *extack)
{}

static void dsa_port_switchdev_unsync_attrs(struct dsa_port *dp,
					    struct dsa_bridge bridge)
{}

static int dsa_port_bridge_create(struct dsa_port *dp,
				  struct net_device *br,
				  struct netlink_ext_ack *extack)
{}

static void dsa_port_bridge_destroy(struct dsa_port *dp,
				    const struct net_device *br)
{}

static bool dsa_port_supports_mst(struct dsa_port *dp)
{}

int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br,
			 struct netlink_ext_ack *extack)
{}

void dsa_port_pre_bridge_leave(struct dsa_port *dp, struct net_device *br)
{}

void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br)
{}

int dsa_port_lag_change(struct dsa_port *dp,
			struct netdev_lag_lower_state_info *linfo)
{}

static int dsa_port_lag_create(struct dsa_port *dp,
			       struct net_device *lag_dev)
{}

static void dsa_port_lag_destroy(struct dsa_port *dp)
{}

int dsa_port_lag_join(struct dsa_port *dp, struct net_device *lag_dev,
		      struct netdev_lag_upper_info *uinfo,
		      struct netlink_ext_ack *extack)
{}

void dsa_port_pre_lag_leave(struct dsa_port *dp, struct net_device *lag_dev)
{}

void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag_dev)
{}

/* Must be called under rcu_read_lock() */
static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp,
					      bool vlan_filtering,
					      struct netlink_ext_ack *extack)
{}

int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
			    struct netlink_ext_ack *extack)
{}

/* This enforces legacy behavior for switch drivers which assume they can't
 * receive VLAN configuration when joining a bridge with vlan_filtering=0
 */
bool dsa_port_skip_vlan_configuration(struct dsa_port *dp)
{}

int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock)
{}

int dsa_port_mst_enable(struct dsa_port *dp, bool on,
			struct netlink_ext_ack *extack)
{}

int dsa_port_pre_bridge_flags(const struct dsa_port *dp,
			      struct switchdev_brport_flags flags,
			      struct netlink_ext_ack *extack)
{}

int dsa_port_bridge_flags(struct dsa_port *dp,
			  struct switchdev_brport_flags flags,
			  struct netlink_ext_ack *extack)
{}

void dsa_port_set_host_flood(struct dsa_port *dp, bool uc, bool mc)
{}

int dsa_port_vlan_msti(struct dsa_port *dp,
		       const struct switchdev_vlan_msti *msti)
{}

int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu)
{}

int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr,
		     u16 vid)
{}

int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr,
		     u16 vid)
{}

static int dsa_port_host_fdb_add(struct dsa_port *dp,
				 const unsigned char *addr, u16 vid,
				 struct dsa_db db)
{}

int dsa_port_standalone_host_fdb_add(struct dsa_port *dp,
				     const unsigned char *addr, u16 vid)
{}

int dsa_port_bridge_host_fdb_add(struct dsa_port *dp,
				 const unsigned char *addr, u16 vid)
{}

static int dsa_port_host_fdb_del(struct dsa_port *dp,
				 const unsigned char *addr, u16 vid,
				 struct dsa_db db)
{}

int dsa_port_standalone_host_fdb_del(struct dsa_port *dp,
				     const unsigned char *addr, u16 vid)
{}

int dsa_port_bridge_host_fdb_del(struct dsa_port *dp,
				 const unsigned char *addr, u16 vid)
{}

int dsa_port_lag_fdb_add(struct dsa_port *dp, const unsigned char *addr,
			 u16 vid)
{}

int dsa_port_lag_fdb_del(struct dsa_port *dp, const unsigned char *addr,
			 u16 vid)
{}

int dsa_port_fdb_dump(struct dsa_port *dp, dsa_fdb_dump_cb_t *cb, void *data)
{}

int dsa_port_mdb_add(const struct dsa_port *dp,
		     const struct switchdev_obj_port_mdb *mdb)
{}

int dsa_port_mdb_del(const struct dsa_port *dp,
		     const struct switchdev_obj_port_mdb *mdb)
{}

static int dsa_port_host_mdb_add(const struct dsa_port *dp,
				 const struct switchdev_obj_port_mdb *mdb,
				 struct dsa_db db)
{}

int dsa_port_standalone_host_mdb_add(const struct dsa_port *dp,
				     const struct switchdev_obj_port_mdb *mdb)
{}

int dsa_port_bridge_host_mdb_add(const struct dsa_port *dp,
				 const struct switchdev_obj_port_mdb *mdb)
{}

static int dsa_port_host_mdb_del(const struct dsa_port *dp,
				 const struct switchdev_obj_port_mdb *mdb,
				 struct dsa_db db)
{}

int dsa_port_standalone_host_mdb_del(const struct dsa_port *dp,
				     const struct switchdev_obj_port_mdb *mdb)
{}

int dsa_port_bridge_host_mdb_del(const struct dsa_port *dp,
				 const struct switchdev_obj_port_mdb *mdb)
{}

int dsa_port_vlan_add(struct dsa_port *dp,
		      const struct switchdev_obj_port_vlan *vlan,
		      struct netlink_ext_ack *extack)
{}

int dsa_port_vlan_del(struct dsa_port *dp,
		      const struct switchdev_obj_port_vlan *vlan)
{}

int dsa_port_host_vlan_add(struct dsa_port *dp,
			   const struct switchdev_obj_port_vlan *vlan,
			   struct netlink_ext_ack *extack)
{}

int dsa_port_host_vlan_del(struct dsa_port *dp,
			   const struct switchdev_obj_port_vlan *vlan)
{}

int dsa_port_mrp_add(const struct dsa_port *dp,
		     const struct switchdev_obj_mrp *mrp)
{}

int dsa_port_mrp_del(const struct dsa_port *dp,
		     const struct switchdev_obj_mrp *mrp)
{}

int dsa_port_mrp_add_ring_role(const struct dsa_port *dp,
			       const struct switchdev_obj_ring_role_mrp *mrp)
{}

int dsa_port_mrp_del_ring_role(const struct dsa_port *dp,
			       const struct switchdev_obj_ring_role_mrp *mrp)
{}

static int dsa_port_assign_conduit(struct dsa_port *dp,
				   struct net_device *conduit,
				   struct netlink_ext_ack *extack,
				   bool fail_on_err)
{}

/* Change the dp->cpu_dp affinity for a user port. Note that both cross-chip
 * notifiers and drivers have implicit assumptions about user-to-CPU-port
 * mappings, so we unfortunately cannot delay the deletion of the objects
 * (switchdev, standalone addresses, standalone VLANs) on the old CPU port
 * until the new CPU port has been set up. So we need to completely tear down
 * the old CPU port before changing it, and restore it on errors during the
 * bringup of the new one.
 */
int dsa_port_change_conduit(struct dsa_port *dp, struct net_device *conduit,
			    struct netlink_ext_ack *extack)
{}

void dsa_port_set_tag_protocol(struct dsa_port *cpu_dp,
			       const struct dsa_device_ops *tag_ops)
{}

static struct phylink_pcs *
dsa_port_phylink_mac_select_pcs(struct phylink_config *config,
				phy_interface_t interface)
{}

static void dsa_port_phylink_mac_config(struct phylink_config *config,
					unsigned int mode,
					const struct phylink_link_state *state)
{}

static void dsa_port_phylink_mac_link_down(struct phylink_config *config,
					   unsigned int mode,
					   phy_interface_t interface)
{}

static void dsa_port_phylink_mac_link_up(struct phylink_config *config,
					 struct phy_device *phydev,
					 unsigned int mode,
					 phy_interface_t interface,
					 int speed, int duplex,
					 bool tx_pause, bool rx_pause)
{}

static const struct phylink_mac_ops dsa_port_phylink_mac_ops =;

int dsa_port_phylink_create(struct dsa_port *dp)
{}

void dsa_port_phylink_destroy(struct dsa_port *dp)
{}

static int dsa_shared_port_phylink_register(struct dsa_port *dp)
{}

/* During the initial DSA driver migration to OF, port nodes were sometimes
 * added to device trees with no indication of how they should operate from a
 * link management perspective (phy-handle, fixed-link, etc). Additionally, the
 * phy-mode may be absent. The interpretation of these port OF nodes depends on
 * their type.
 *
 * User ports with no phy-handle or fixed-link are expected to connect to an
 * internal PHY located on the ds->user_mii_bus at an MDIO address equal to
 * the port number. This description is still actively supported.
 *
 * Shared (CPU and DSA) ports with no phy-handle or fixed-link are expected to
 * operate at the maximum speed that their phy-mode is capable of. If the
 * phy-mode is absent, they are expected to operate using the phy-mode
 * supported by the port that gives the highest link speed. It is unspecified
 * if the port should use flow control or not, half duplex or full duplex, or
 * if the phy-mode is a SERDES link, whether in-band autoneg is expected to be
 * enabled or not.
 *
 * In the latter case of shared ports, omitting the link management description
 * from the firmware node is deprecated and strongly discouraged. DSA uses
 * phylink, which rejects the firmware nodes of these ports for lacking
 * required properties.
 *
 * For switches in this table, DSA will skip enforcing validation and will
 * later omit registering a phylink instance for the shared ports, if they lack
 * a fixed-link, a phy-handle, or a managed = "in-band-status" property.
 * It becomes the responsibility of the driver to ensure that these ports
 * operate at the maximum speed (whatever this means) and will interoperate
 * with the DSA conduit or other cascade port, since phylink methods will not be
 * invoked for them.
 *
 * If you are considering expanding this table for newly introduced switches,
 * think again. It is OK to remove switches from this table if there aren't DT
 * blobs in circulation which rely on defaulting the shared ports.
 */
static const char * const dsa_switches_apply_workarounds[] =;

static void dsa_shared_port_validate_of(struct dsa_port *dp,
					bool *missing_phy_mode,
					bool *missing_link_description)
{}

static void dsa_shared_port_link_down(struct dsa_port *dp)
{}

int dsa_shared_port_link_register_of(struct dsa_port *dp)
{}

void dsa_shared_port_link_unregister_of(struct dsa_port *dp)
{}

int dsa_port_hsr_join(struct dsa_port *dp, struct net_device *hsr,
		      struct netlink_ext_ack *extack)
{}

void dsa_port_hsr_leave(struct dsa_port *dp, struct net_device *hsr)
{}

int dsa_port_tag_8021q_vlan_add(struct dsa_port *dp, u16 vid, bool broadcast)
{}

void dsa_port_tag_8021q_vlan_del(struct dsa_port *dp, u16 vid, bool broadcast)
{}