linux/net/dsa/dsa.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * DSA topology and switch handling
 *
 * Copyright (c) 2008-2009 Marvell Semiconductor
 * Copyright (c) 2013 Florian Fainelli <[email protected]>
 * Copyright (c) 2016 Andrew Lunn <[email protected]>
 */

#include <linux/device.h>
#include <linux/err.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/slab.h>
#include <linux/rtnetlink.h>
#include <linux/of.h>
#include <linux/of_net.h>
#include <net/dsa_stubs.h>
#include <net/sch_generic.h>

#include "conduit.h"
#include "devlink.h"
#include "dsa.h"
#include "netlink.h"
#include "port.h"
#include "switch.h"
#include "tag.h"
#include "user.h"

#define DSA_MAX_NUM_OFFLOADING_BRIDGES

static DEFINE_MUTEX(dsa2_mutex);
LIST_HEAD();

static struct workqueue_struct *dsa_owq;

/* Track the bridges with forwarding offload enabled */
static unsigned long dsa_fwd_offloading_bridges;

bool dsa_schedule_work(struct work_struct *work)
{}

void dsa_flush_workqueue(void)
{}
EXPORT_SYMBOL_GPL();

/**
 * dsa_lag_map() - Map LAG structure to a linear LAG array
 * @dst: Tree in which to record the mapping.
 * @lag: LAG structure that is to be mapped to the tree's array.
 *
 * dsa_lag_id/dsa_lag_by_id can then be used to translate between the
 * two spaces. The size of the mapping space is determined by the
 * driver by setting ds->num_lag_ids. It is perfectly legal to leave
 * it unset if it is not needed, in which case these functions become
 * no-ops.
 */
void dsa_lag_map(struct dsa_switch_tree *dst, struct dsa_lag *lag)
{}

/**
 * dsa_lag_unmap() - Remove a LAG ID mapping
 * @dst: Tree in which the mapping is recorded.
 * @lag: LAG structure that was mapped.
 *
 * As there may be multiple users of the mapping, it is only removed
 * if there are no other references to it.
 */
void dsa_lag_unmap(struct dsa_switch_tree *dst, struct dsa_lag *lag)
{}

struct dsa_lag *dsa_tree_lag_find(struct dsa_switch_tree *dst,
				  const struct net_device *lag_dev)
{}

struct dsa_bridge *dsa_tree_bridge_find(struct dsa_switch_tree *dst,
					const struct net_device *br)
{}

static int dsa_bridge_num_find(const struct net_device *bridge_dev)
{}

unsigned int dsa_bridge_num_get(const struct net_device *bridge_dev, int max)
{}

void dsa_bridge_num_put(const struct net_device *bridge_dev,
			unsigned int bridge_num)
{}

struct dsa_switch *dsa_switch_find(int tree_index, int sw_index)
{}
EXPORT_SYMBOL_GPL();

static struct dsa_switch_tree *dsa_tree_find(int index)
{}

static struct dsa_switch_tree *dsa_tree_alloc(int index)
{}

static void dsa_tree_free(struct dsa_switch_tree *dst)
{}

static struct dsa_switch_tree *dsa_tree_get(struct dsa_switch_tree *dst)
{}

static struct dsa_switch_tree *dsa_tree_touch(int index)
{}

static void dsa_tree_release(struct kref *ref)
{}

static void dsa_tree_put(struct dsa_switch_tree *dst)
{}

static struct dsa_port *dsa_tree_find_port_by_node(struct dsa_switch_tree *dst,
						   struct device_node *dn)
{}

static struct dsa_link *dsa_link_touch(struct dsa_port *dp,
				       struct dsa_port *link_dp)
{}

static bool dsa_port_setup_routing_table(struct dsa_port *dp)
{}

static bool dsa_tree_setup_routing_table(struct dsa_switch_tree *dst)
{}

static struct dsa_port *dsa_tree_find_first_cpu(struct dsa_switch_tree *dst)
{}

struct net_device *dsa_tree_find_first_conduit(struct dsa_switch_tree *dst)
{}

/* Assign the default CPU port (the first one in the tree) to all ports of the
 * fabric which don't already have one as part of their own switch.
 */
static int dsa_tree_setup_default_cpu(struct dsa_switch_tree *dst)
{}

static struct dsa_port *
dsa_switch_preferred_default_local_cpu_port(struct dsa_switch *ds)
{}

/* Perform initial assignment of CPU ports to user ports and DSA links in the
 * fabric, giving preference to CPU ports local to each switch. Default to
 * using the first CPU port in the switch tree if the port does not have a CPU
 * port local to this switch.
 */
static int dsa_tree_setup_cpu_ports(struct dsa_switch_tree *dst)
{}

static void dsa_tree_teardown_cpu_ports(struct dsa_switch_tree *dst)
{}

static int dsa_port_setup(struct dsa_port *dp)
{}

static void dsa_port_teardown(struct dsa_port *dp)
{}

static int dsa_port_setup_as_unused(struct dsa_port *dp)
{}

static int dsa_switch_setup_tag_protocol(struct dsa_switch *ds)
{}

static void dsa_switch_teardown_tag_protocol(struct dsa_switch *ds)
{}

static int dsa_switch_setup(struct dsa_switch *ds)
{}

static void dsa_switch_teardown(struct dsa_switch *ds)
{}

/* First tear down the non-shared, then the shared ports. This ensures that
 * all work items scheduled by our switchdev handlers for user ports have
 * completed before we destroy the refcounting kept on the shared ports.
 */
static void dsa_tree_teardown_ports(struct dsa_switch_tree *dst)
{}

static void dsa_tree_teardown_switches(struct dsa_switch_tree *dst)
{}

/* Bring shared ports up first, then non-shared ports */
static int dsa_tree_setup_ports(struct dsa_switch_tree *dst)
{}

static int dsa_tree_setup_switches(struct dsa_switch_tree *dst)
{}

static int dsa_tree_setup_conduit(struct dsa_switch_tree *dst)
{}

static void dsa_tree_teardown_conduit(struct dsa_switch_tree *dst)
{}

static int dsa_tree_setup_lags(struct dsa_switch_tree *dst)
{}

static void dsa_tree_teardown_lags(struct dsa_switch_tree *dst)
{}

static int dsa_tree_setup(struct dsa_switch_tree *dst)
{}

static void dsa_tree_teardown(struct dsa_switch_tree *dst)
{}

static int dsa_tree_bind_tag_proto(struct dsa_switch_tree *dst,
				   const struct dsa_device_ops *tag_ops)
{}

/* Since the dsa/tagging sysfs device attribute is per conduit, the assumption
 * is that all DSA switches within a tree share the same tagger, otherwise
 * they would have formed disjoint trees (different "dsa,member" values).
 */
int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst,
			      const struct dsa_device_ops *tag_ops,
			      const struct dsa_device_ops *old_tag_ops)
{}

static void dsa_tree_conduit_state_change(struct dsa_switch_tree *dst,
					  struct net_device *conduit)
{}

void dsa_tree_conduit_admin_state_change(struct dsa_switch_tree *dst,
					 struct net_device *conduit,
					 bool up)
{}

void dsa_tree_conduit_oper_state_change(struct dsa_switch_tree *dst,
					struct net_device *conduit,
					bool up)
{}

static struct dsa_port *dsa_port_touch(struct dsa_switch *ds, int index)
{}

static int dsa_port_parse_user(struct dsa_port *dp, const char *name)
{}

static int dsa_port_parse_dsa(struct dsa_port *dp)
{}

static enum dsa_tag_protocol dsa_get_tag_protocol(struct dsa_port *dp,
						  struct net_device *conduit)
{}

static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *conduit,
			      const char *user_protocol)
{}

static int dsa_port_parse_of(struct dsa_port *dp, struct device_node *dn)
{}

static int dsa_switch_parse_ports_of(struct dsa_switch *ds,
				     struct device_node *dn)
{}

static int dsa_switch_parse_member_of(struct dsa_switch *ds,
				      struct device_node *dn)
{}

static int dsa_switch_touch_ports(struct dsa_switch *ds)
{}

static int dsa_switch_parse_of(struct dsa_switch *ds, struct device_node *dn)
{}

static int dev_is_class(struct device *dev, void *class)
{}

static struct device *dev_find_class(struct device *parent, char *class)
{}

static struct net_device *dsa_dev_to_net_device(struct device *dev)
{}

static int dsa_port_parse(struct dsa_port *dp, const char *name,
			  struct device *dev)
{}

static int dsa_switch_parse_ports(struct dsa_switch *ds,
				  struct dsa_chip_data *cd)
{}

static int dsa_switch_parse(struct dsa_switch *ds, struct dsa_chip_data *cd)
{}

static void dsa_switch_release_ports(struct dsa_switch *ds)
{}

static int dsa_switch_probe(struct dsa_switch *ds)
{}

int dsa_register_switch(struct dsa_switch *ds)
{}
EXPORT_SYMBOL_GPL();

static void dsa_switch_remove(struct dsa_switch *ds)
{}

void dsa_unregister_switch(struct dsa_switch *ds)
{}
EXPORT_SYMBOL_GPL();

/* If the DSA conduit chooses to unregister its net_device on .shutdown, DSA is
 * blocking that operation from completion, due to the dev_hold taken inside
 * netdev_upper_dev_link. Unlink the DSA user interfaces from being uppers of
 * the DSA conduit, so that the system can reboot successfully.
 */
void dsa_switch_shutdown(struct dsa_switch *ds)
{}
EXPORT_SYMBOL_GPL();

#ifdef CONFIG_PM_SLEEP
static bool dsa_port_is_initialized(const struct dsa_port *dp)
{}

int dsa_switch_suspend(struct dsa_switch *ds)
{}
EXPORT_SYMBOL_GPL();

int dsa_switch_resume(struct dsa_switch *ds)
{}
EXPORT_SYMBOL_GPL();
#endif

struct dsa_port *dsa_port_from_netdev(struct net_device *netdev)
{}
EXPORT_SYMBOL_GPL();

bool dsa_db_equal(const struct dsa_db *a, const struct dsa_db *b)
{}

bool dsa_fdb_present_in_other_db(struct dsa_switch *ds, int port,
				 const unsigned char *addr, u16 vid,
				 struct dsa_db db)
{}
EXPORT_SYMBOL_GPL();

bool dsa_mdb_present_in_other_db(struct dsa_switch *ds, int port,
				 const struct switchdev_obj_port_mdb *mdb,
				 struct dsa_db db)
{}
EXPORT_SYMBOL_GPL();

static const struct dsa_stubs __dsa_stubs =;

static void dsa_register_stubs(void)
{}

static void dsa_unregister_stubs(void)
{}

static int __init dsa_init_module(void)
{}
module_init();

static void __exit dsa_cleanup_module(void)
{}
module_exit(dsa_cleanup_module);

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_ALIAS();