linux/include/net/dsa.h

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * include/net/dsa.h - Driver for Distributed Switch Architecture switch chips
 * Copyright (c) 2008-2009 Marvell Semiconductor
 */

#ifndef __LINUX_NET_DSA_H
#define __LINUX_NET_DSA_H

#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/list.h>
#include <linux/notifier.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <linux/of.h>
#include <linux/ethtool.h>
#include <linux/net_tstamp.h>
#include <linux/phy.h>
#include <linux/platform_data/dsa.h>
#include <linux/phylink.h>
#include <net/devlink.h>
#include <net/switchdev.h>

struct dsa_8021q_context;
struct tc_action;

#define DSA_TAG_PROTO_NONE_VALUE
#define DSA_TAG_PROTO_BRCM_VALUE
#define DSA_TAG_PROTO_BRCM_PREPEND_VALUE
#define DSA_TAG_PROTO_DSA_VALUE
#define DSA_TAG_PROTO_EDSA_VALUE
#define DSA_TAG_PROTO_GSWIP_VALUE
#define DSA_TAG_PROTO_KSZ9477_VALUE
#define DSA_TAG_PROTO_KSZ9893_VALUE
#define DSA_TAG_PROTO_LAN9303_VALUE
#define DSA_TAG_PROTO_MTK_VALUE
#define DSA_TAG_PROTO_QCA_VALUE
#define DSA_TAG_PROTO_TRAILER_VALUE
#define DSA_TAG_PROTO_8021Q_VALUE
#define DSA_TAG_PROTO_SJA1105_VALUE
#define DSA_TAG_PROTO_KSZ8795_VALUE
#define DSA_TAG_PROTO_OCELOT_VALUE
#define DSA_TAG_PROTO_AR9331_VALUE
#define DSA_TAG_PROTO_RTL4_A_VALUE
#define DSA_TAG_PROTO_HELLCREEK_VALUE
#define DSA_TAG_PROTO_XRS700X_VALUE
#define DSA_TAG_PROTO_OCELOT_8021Q_VALUE
#define DSA_TAG_PROTO_SEVILLE_VALUE
#define DSA_TAG_PROTO_BRCM_LEGACY_VALUE
#define DSA_TAG_PROTO_SJA1110_VALUE
#define DSA_TAG_PROTO_RTL8_4_VALUE
#define DSA_TAG_PROTO_RTL8_4T_VALUE
#define DSA_TAG_PROTO_RZN1_A5PSW_VALUE
#define DSA_TAG_PROTO_LAN937X_VALUE
#define DSA_TAG_PROTO_VSC73XX_8021Q_VALUE

enum dsa_tag_protocol {};

struct dsa_switch;

struct dsa_device_ops {};

struct dsa_lag {};

struct dsa_switch_tree {};

/* LAG IDs are one-based, the dst->lags array is zero-based */
#define dsa_lags_foreach_id(_id, _dst)

#define dsa_lag_foreach_port(_dp, _dst, _lag)

#define dsa_hsr_foreach_port(_dp, _ds, _hsr)

static inline struct dsa_lag *dsa_lag_by_id(struct dsa_switch_tree *dst,
					    unsigned int id)
{}

static inline int dsa_lag_id(struct dsa_switch_tree *dst,
			     struct net_device *lag_dev)
{}

/* TC matchall action types */
enum dsa_port_mall_action_type {};

/* TC mirroring entry */
struct dsa_mall_mirror_tc_entry {};

/* TC port policer entry */
struct dsa_mall_policer_tc_entry {};

/* TC matchall entry */
struct dsa_mall_tc_entry {};

struct dsa_bridge {};

struct dsa_port {};

static inline struct dsa_port *
dsa_phylink_to_port(struct phylink_config *config)
{}

/* TODO: ideally DSA ports would have a single dp->link_dp member,
 * and no dst->rtable nor this struct dsa_link would be needed,
 * but this would require some more complex tree walking,
 * so keep it stupid at the moment and list them all.
 */
struct dsa_link {};

enum dsa_db_type {};

struct dsa_db {};

struct dsa_mac_addr {};

struct dsa_vlan {};

struct dsa_switch {};

static inline struct dsa_port *dsa_to_port(struct dsa_switch *ds, int p)
{}

static inline bool dsa_port_is_dsa(struct dsa_port *port)
{}

static inline bool dsa_port_is_cpu(struct dsa_port *port)
{}

static inline bool dsa_port_is_user(struct dsa_port *dp)
{}

static inline bool dsa_port_is_unused(struct dsa_port *dp)
{}

static inline bool dsa_port_conduit_is_operational(struct dsa_port *dp)
{}

static inline bool dsa_is_unused_port(struct dsa_switch *ds, int p)
{}

static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p)
{}

static inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p)
{}

static inline bool dsa_is_user_port(struct dsa_switch *ds, int p)
{}

#define dsa_tree_for_each_user_port(_dp, _dst)

#define dsa_tree_for_each_user_port_continue_reverse(_dp, _dst)

#define dsa_tree_for_each_cpu_port(_dp, _dst)

#define dsa_switch_for_each_port(_dp, _ds)

#define dsa_switch_for_each_port_safe(_dp, _next, _ds)

#define dsa_switch_for_each_port_continue_reverse(_dp, _ds)

#define dsa_switch_for_each_available_port(_dp, _ds)

#define dsa_switch_for_each_user_port(_dp, _ds)

#define dsa_switch_for_each_user_port_continue_reverse(_dp, _ds)

#define dsa_switch_for_each_cpu_port(_dp, _ds)

#define dsa_switch_for_each_cpu_port_continue_reverse(_dp, _ds)

static inline u32 dsa_user_ports(struct dsa_switch *ds)
{}

static inline u32 dsa_cpu_ports(struct dsa_switch *ds)
{}

/* Return the local port used to reach an arbitrary switch device */
static inline unsigned int dsa_routing_port(struct dsa_switch *ds, int device)
{}

/* Return the local port used to reach an arbitrary switch port */
static inline unsigned int dsa_towards_port(struct dsa_switch *ds, int device,
					    int port)
{}

/* Return the local port used to reach the dedicated CPU port */
static inline unsigned int dsa_upstream_port(struct dsa_switch *ds, int port)
{}

/* Return true if this is the local port used to reach the CPU port */
static inline bool dsa_is_upstream_port(struct dsa_switch *ds, int port)
{}

/* Return true if this is a DSA port leading away from the CPU */
static inline bool dsa_is_downstream_port(struct dsa_switch *ds, int port)
{}

/* Return the local port used to reach the CPU port */
static inline unsigned int dsa_switch_upstream_port(struct dsa_switch *ds)
{}

/* Return true if @upstream_ds is an upstream switch of @downstream_ds, meaning
 * that the routing port from @downstream_ds to @upstream_ds is also the port
 * which @downstream_ds uses to reach its dedicated CPU.
 */
static inline bool dsa_switch_is_upstream_of(struct dsa_switch *upstream_ds,
					     struct dsa_switch *downstream_ds)
{}

static inline bool dsa_port_is_vlan_filtering(const struct dsa_port *dp)
{}

static inline unsigned int dsa_port_lag_id_get(struct dsa_port *dp)
{}

static inline struct net_device *dsa_port_lag_dev_get(struct dsa_port *dp)
{}

static inline bool dsa_port_offloads_lag(struct dsa_port *dp,
					 const struct dsa_lag *lag)
{}

static inline struct net_device *dsa_port_to_conduit(const struct dsa_port *dp)
{}

static inline
struct net_device *dsa_port_to_bridge_port(const struct dsa_port *dp)
{}

static inline struct net_device *
dsa_port_bridge_dev_get(const struct dsa_port *dp)
{}

static inline unsigned int dsa_port_bridge_num_get(struct dsa_port *dp)
{}

static inline bool dsa_port_bridge_same(const struct dsa_port *a,
					const struct dsa_port *b)
{}

static inline bool dsa_port_offloads_bridge_port(struct dsa_port *dp,
						 const struct net_device *dev)
{}

static inline bool
dsa_port_offloads_bridge_dev(struct dsa_port *dp,
			     const struct net_device *bridge_dev)
{}

static inline bool dsa_port_offloads_bridge(struct dsa_port *dp,
					    const struct dsa_bridge *bridge)
{}

/* Returns true if any port of this tree offloads the given net_device */
static inline bool dsa_tree_offloads_bridge_port(struct dsa_switch_tree *dst,
						 const struct net_device *dev)
{}

/* Returns true if any port of this tree offloads the given bridge */
static inline bool
dsa_tree_offloads_bridge_dev(struct dsa_switch_tree *dst,
			     const struct net_device *bridge_dev)
{}

static inline bool dsa_port_tree_same(const struct dsa_port *a,
				      const struct dsa_port *b)
{}

dsa_fdb_dump_cb_t;
struct dsa_switch_ops {};

#define DSA_DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes)

int dsa_devlink_param_get(struct devlink *dl, u32 id,
			  struct devlink_param_gset_ctx *ctx);
int dsa_devlink_param_set(struct devlink *dl, u32 id,
			  struct devlink_param_gset_ctx *ctx,
			  struct netlink_ext_ack *extack);
int dsa_devlink_params_register(struct dsa_switch *ds,
				const struct devlink_param *params,
				size_t params_count);
void dsa_devlink_params_unregister(struct dsa_switch *ds,
				   const struct devlink_param *params,
				   size_t params_count);
int dsa_devlink_resource_register(struct dsa_switch *ds,
				  const char *resource_name,
				  u64 resource_size,
				  u64 resource_id,
				  u64 parent_resource_id,
				  const struct devlink_resource_size_params *size_params);

void dsa_devlink_resources_unregister(struct dsa_switch *ds);

void dsa_devlink_resource_occ_get_register(struct dsa_switch *ds,
					   u64 resource_id,
					   devlink_resource_occ_get_t *occ_get,
					   void *occ_get_priv);
void dsa_devlink_resource_occ_get_unregister(struct dsa_switch *ds,
					     u64 resource_id);
struct devlink_region *
dsa_devlink_region_create(struct dsa_switch *ds,
			  const struct devlink_region_ops *ops,
			  u32 region_max_snapshots, u64 region_size);
struct devlink_region *
dsa_devlink_port_region_create(struct dsa_switch *ds,
			       int port,
			       const struct devlink_port_region_ops *ops,
			       u32 region_max_snapshots, u64 region_size);
void dsa_devlink_region_destroy(struct devlink_region *region);

struct dsa_port *dsa_port_from_netdev(struct net_device *netdev);

struct dsa_devlink_priv {};

static inline struct dsa_switch *dsa_devlink_to_ds(struct devlink *dl)
{}

static inline
struct dsa_switch *dsa_devlink_port_to_ds(struct devlink_port *port)
{}

static inline int dsa_devlink_port_to_port(struct devlink_port *port)
{}

struct dsa_switch_driver {};

bool dsa_fdb_present_in_other_db(struct dsa_switch *ds, int port,
				 const unsigned char *addr, u16 vid,
				 struct dsa_db db);
bool dsa_mdb_present_in_other_db(struct dsa_switch *ds, int port,
				 const struct switchdev_obj_port_mdb *mdb,
				 struct dsa_db db);

/* Keep inline for faster access in hot path */
static inline bool netdev_uses_dsa(const struct net_device *dev)
{}

/* All DSA tags that push the EtherType to the right (basically all except tail
 * tags, which don't break dissection) can be treated the same from the
 * perspective of the flow dissector.
 *
 * We need to return:
 *  - offset: the (B - A) difference between:
 *    A. the position of the real EtherType and
 *    B. the current skb->data (aka ETH_HLEN bytes into the frame, aka 2 bytes
 *       after the normal EtherType was supposed to be)
 *    The offset in bytes is exactly equal to the tagger overhead (and half of
 *    that, in __be16 shorts).
 *
 *  - proto: the value of the real EtherType.
 */
static inline void dsa_tag_generic_flow_dissect(const struct sk_buff *skb,
						__be16 *proto, int *offset)
{}

void dsa_unregister_switch(struct dsa_switch *ds);
int dsa_register_switch(struct dsa_switch *ds);
void dsa_switch_shutdown(struct dsa_switch *ds);
struct dsa_switch *dsa_switch_find(int tree_index, int sw_index);
void dsa_flush_workqueue(void);
#ifdef CONFIG_PM_SLEEP
int dsa_switch_suspend(struct dsa_switch *ds);
int dsa_switch_resume(struct dsa_switch *ds);
#else
static inline int dsa_switch_suspend(struct dsa_switch *ds)
{
	return 0;
}
static inline int dsa_switch_resume(struct dsa_switch *ds)
{
	return 0;
}
#endif /* CONFIG_PM_SLEEP */

#if IS_ENABLED(CONFIG_NET_DSA)
bool dsa_user_dev_check(const struct net_device *dev);
#else
static inline bool dsa_user_dev_check(const struct net_device *dev)
{
	return false;
}
#endif

netdev_tx_t dsa_enqueue_skb(struct sk_buff *skb, struct net_device *dev);
void dsa_port_phylink_mac_change(struct dsa_switch *ds, int port, bool up);

#endif