162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * include/net/dsa.h - Driver for Distributed Switch Architecture switch chips
462306a36Sopenharmony_ci * Copyright (c) 2008-2009 Marvell Semiconductor
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef __LINUX_NET_DSA_H
862306a36Sopenharmony_ci#define __LINUX_NET_DSA_H
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/if.h>
1162306a36Sopenharmony_ci#include <linux/if_ether.h>
1262306a36Sopenharmony_ci#include <linux/list.h>
1362306a36Sopenharmony_ci#include <linux/notifier.h>
1462306a36Sopenharmony_ci#include <linux/timer.h>
1562306a36Sopenharmony_ci#include <linux/workqueue.h>
1662306a36Sopenharmony_ci#include <linux/of.h>
1762306a36Sopenharmony_ci#include <linux/ethtool.h>
1862306a36Sopenharmony_ci#include <linux/net_tstamp.h>
1962306a36Sopenharmony_ci#include <linux/phy.h>
2062306a36Sopenharmony_ci#include <linux/platform_data/dsa.h>
2162306a36Sopenharmony_ci#include <linux/phylink.h>
2262306a36Sopenharmony_ci#include <net/devlink.h>
2362306a36Sopenharmony_ci#include <net/switchdev.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistruct dsa_8021q_context;
2662306a36Sopenharmony_cistruct tc_action;
2762306a36Sopenharmony_cistruct phy_device;
2862306a36Sopenharmony_cistruct fixed_phy_status;
2962306a36Sopenharmony_cistruct phylink_link_state;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define DSA_TAG_PROTO_NONE_VALUE		0
3262306a36Sopenharmony_ci#define DSA_TAG_PROTO_BRCM_VALUE		1
3362306a36Sopenharmony_ci#define DSA_TAG_PROTO_BRCM_PREPEND_VALUE	2
3462306a36Sopenharmony_ci#define DSA_TAG_PROTO_DSA_VALUE			3
3562306a36Sopenharmony_ci#define DSA_TAG_PROTO_EDSA_VALUE		4
3662306a36Sopenharmony_ci#define DSA_TAG_PROTO_GSWIP_VALUE		5
3762306a36Sopenharmony_ci#define DSA_TAG_PROTO_KSZ9477_VALUE		6
3862306a36Sopenharmony_ci#define DSA_TAG_PROTO_KSZ9893_VALUE		7
3962306a36Sopenharmony_ci#define DSA_TAG_PROTO_LAN9303_VALUE		8
4062306a36Sopenharmony_ci#define DSA_TAG_PROTO_MTK_VALUE			9
4162306a36Sopenharmony_ci#define DSA_TAG_PROTO_QCA_VALUE			10
4262306a36Sopenharmony_ci#define DSA_TAG_PROTO_TRAILER_VALUE		11
4362306a36Sopenharmony_ci#define DSA_TAG_PROTO_8021Q_VALUE		12
4462306a36Sopenharmony_ci#define DSA_TAG_PROTO_SJA1105_VALUE		13
4562306a36Sopenharmony_ci#define DSA_TAG_PROTO_KSZ8795_VALUE		14
4662306a36Sopenharmony_ci#define DSA_TAG_PROTO_OCELOT_VALUE		15
4762306a36Sopenharmony_ci#define DSA_TAG_PROTO_AR9331_VALUE		16
4862306a36Sopenharmony_ci#define DSA_TAG_PROTO_RTL4_A_VALUE		17
4962306a36Sopenharmony_ci#define DSA_TAG_PROTO_HELLCREEK_VALUE		18
5062306a36Sopenharmony_ci#define DSA_TAG_PROTO_XRS700X_VALUE		19
5162306a36Sopenharmony_ci#define DSA_TAG_PROTO_OCELOT_8021Q_VALUE	20
5262306a36Sopenharmony_ci#define DSA_TAG_PROTO_SEVILLE_VALUE		21
5362306a36Sopenharmony_ci#define DSA_TAG_PROTO_BRCM_LEGACY_VALUE		22
5462306a36Sopenharmony_ci#define DSA_TAG_PROTO_SJA1110_VALUE		23
5562306a36Sopenharmony_ci#define DSA_TAG_PROTO_RTL8_4_VALUE		24
5662306a36Sopenharmony_ci#define DSA_TAG_PROTO_RTL8_4T_VALUE		25
5762306a36Sopenharmony_ci#define DSA_TAG_PROTO_RZN1_A5PSW_VALUE		26
5862306a36Sopenharmony_ci#define DSA_TAG_PROTO_LAN937X_VALUE		27
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cienum dsa_tag_protocol {
6162306a36Sopenharmony_ci	DSA_TAG_PROTO_NONE		= DSA_TAG_PROTO_NONE_VALUE,
6262306a36Sopenharmony_ci	DSA_TAG_PROTO_BRCM		= DSA_TAG_PROTO_BRCM_VALUE,
6362306a36Sopenharmony_ci	DSA_TAG_PROTO_BRCM_LEGACY	= DSA_TAG_PROTO_BRCM_LEGACY_VALUE,
6462306a36Sopenharmony_ci	DSA_TAG_PROTO_BRCM_PREPEND	= DSA_TAG_PROTO_BRCM_PREPEND_VALUE,
6562306a36Sopenharmony_ci	DSA_TAG_PROTO_DSA		= DSA_TAG_PROTO_DSA_VALUE,
6662306a36Sopenharmony_ci	DSA_TAG_PROTO_EDSA		= DSA_TAG_PROTO_EDSA_VALUE,
6762306a36Sopenharmony_ci	DSA_TAG_PROTO_GSWIP		= DSA_TAG_PROTO_GSWIP_VALUE,
6862306a36Sopenharmony_ci	DSA_TAG_PROTO_KSZ9477		= DSA_TAG_PROTO_KSZ9477_VALUE,
6962306a36Sopenharmony_ci	DSA_TAG_PROTO_KSZ9893		= DSA_TAG_PROTO_KSZ9893_VALUE,
7062306a36Sopenharmony_ci	DSA_TAG_PROTO_LAN9303		= DSA_TAG_PROTO_LAN9303_VALUE,
7162306a36Sopenharmony_ci	DSA_TAG_PROTO_MTK		= DSA_TAG_PROTO_MTK_VALUE,
7262306a36Sopenharmony_ci	DSA_TAG_PROTO_QCA		= DSA_TAG_PROTO_QCA_VALUE,
7362306a36Sopenharmony_ci	DSA_TAG_PROTO_TRAILER		= DSA_TAG_PROTO_TRAILER_VALUE,
7462306a36Sopenharmony_ci	DSA_TAG_PROTO_8021Q		= DSA_TAG_PROTO_8021Q_VALUE,
7562306a36Sopenharmony_ci	DSA_TAG_PROTO_SJA1105		= DSA_TAG_PROTO_SJA1105_VALUE,
7662306a36Sopenharmony_ci	DSA_TAG_PROTO_KSZ8795		= DSA_TAG_PROTO_KSZ8795_VALUE,
7762306a36Sopenharmony_ci	DSA_TAG_PROTO_OCELOT		= DSA_TAG_PROTO_OCELOT_VALUE,
7862306a36Sopenharmony_ci	DSA_TAG_PROTO_AR9331		= DSA_TAG_PROTO_AR9331_VALUE,
7962306a36Sopenharmony_ci	DSA_TAG_PROTO_RTL4_A		= DSA_TAG_PROTO_RTL4_A_VALUE,
8062306a36Sopenharmony_ci	DSA_TAG_PROTO_HELLCREEK		= DSA_TAG_PROTO_HELLCREEK_VALUE,
8162306a36Sopenharmony_ci	DSA_TAG_PROTO_XRS700X		= DSA_TAG_PROTO_XRS700X_VALUE,
8262306a36Sopenharmony_ci	DSA_TAG_PROTO_OCELOT_8021Q	= DSA_TAG_PROTO_OCELOT_8021Q_VALUE,
8362306a36Sopenharmony_ci	DSA_TAG_PROTO_SEVILLE		= DSA_TAG_PROTO_SEVILLE_VALUE,
8462306a36Sopenharmony_ci	DSA_TAG_PROTO_SJA1110		= DSA_TAG_PROTO_SJA1110_VALUE,
8562306a36Sopenharmony_ci	DSA_TAG_PROTO_RTL8_4		= DSA_TAG_PROTO_RTL8_4_VALUE,
8662306a36Sopenharmony_ci	DSA_TAG_PROTO_RTL8_4T		= DSA_TAG_PROTO_RTL8_4T_VALUE,
8762306a36Sopenharmony_ci	DSA_TAG_PROTO_RZN1_A5PSW	= DSA_TAG_PROTO_RZN1_A5PSW_VALUE,
8862306a36Sopenharmony_ci	DSA_TAG_PROTO_LAN937X		= DSA_TAG_PROTO_LAN937X_VALUE,
8962306a36Sopenharmony_ci};
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_cistruct dsa_switch;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistruct dsa_device_ops {
9462306a36Sopenharmony_ci	struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
9562306a36Sopenharmony_ci	struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev);
9662306a36Sopenharmony_ci	void (*flow_dissect)(const struct sk_buff *skb, __be16 *proto,
9762306a36Sopenharmony_ci			     int *offset);
9862306a36Sopenharmony_ci	int (*connect)(struct dsa_switch *ds);
9962306a36Sopenharmony_ci	void (*disconnect)(struct dsa_switch *ds);
10062306a36Sopenharmony_ci	unsigned int needed_headroom;
10162306a36Sopenharmony_ci	unsigned int needed_tailroom;
10262306a36Sopenharmony_ci	const char *name;
10362306a36Sopenharmony_ci	enum dsa_tag_protocol proto;
10462306a36Sopenharmony_ci	/* Some tagging protocols either mangle or shift the destination MAC
10562306a36Sopenharmony_ci	 * address, in which case the DSA master would drop packets on ingress
10662306a36Sopenharmony_ci	 * if what it understands out of the destination MAC address is not in
10762306a36Sopenharmony_ci	 * its RX filter.
10862306a36Sopenharmony_ci	 */
10962306a36Sopenharmony_ci	bool promisc_on_master;
11062306a36Sopenharmony_ci};
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistruct dsa_lag {
11362306a36Sopenharmony_ci	struct net_device *dev;
11462306a36Sopenharmony_ci	unsigned int id;
11562306a36Sopenharmony_ci	struct mutex fdb_lock;
11662306a36Sopenharmony_ci	struct list_head fdbs;
11762306a36Sopenharmony_ci	refcount_t refcount;
11862306a36Sopenharmony_ci};
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cistruct dsa_switch_tree {
12162306a36Sopenharmony_ci	struct list_head	list;
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	/* List of switch ports */
12462306a36Sopenharmony_ci	struct list_head ports;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	/* Notifier chain for switch-wide events */
12762306a36Sopenharmony_ci	struct raw_notifier_head	nh;
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	/* Tree identifier */
13062306a36Sopenharmony_ci	unsigned int index;
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	/* Number of switches attached to this tree */
13362306a36Sopenharmony_ci	struct kref refcount;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	/* Maps offloaded LAG netdevs to a zero-based linear ID for
13662306a36Sopenharmony_ci	 * drivers that need it.
13762306a36Sopenharmony_ci	 */
13862306a36Sopenharmony_ci	struct dsa_lag **lags;
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	/* Tagging protocol operations */
14162306a36Sopenharmony_ci	const struct dsa_device_ops *tag_ops;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	/* Default tagging protocol preferred by the switches in this
14462306a36Sopenharmony_ci	 * tree.
14562306a36Sopenharmony_ci	 */
14662306a36Sopenharmony_ci	enum dsa_tag_protocol default_proto;
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	/* Has this tree been applied to the hardware? */
14962306a36Sopenharmony_ci	bool setup;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	/*
15262306a36Sopenharmony_ci	 * Configuration data for the platform device that owns
15362306a36Sopenharmony_ci	 * this dsa switch tree instance.
15462306a36Sopenharmony_ci	 */
15562306a36Sopenharmony_ci	struct dsa_platform_data	*pd;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	/* List of DSA links composing the routing table */
15862306a36Sopenharmony_ci	struct list_head rtable;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	/* Length of "lags" array */
16162306a36Sopenharmony_ci	unsigned int lags_len;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	/* Track the largest switch index within a tree */
16462306a36Sopenharmony_ci	unsigned int last_switch;
16562306a36Sopenharmony_ci};
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci/* LAG IDs are one-based, the dst->lags array is zero-based */
16862306a36Sopenharmony_ci#define dsa_lags_foreach_id(_id, _dst)				\
16962306a36Sopenharmony_ci	for ((_id) = 1; (_id) <= (_dst)->lags_len; (_id)++)	\
17062306a36Sopenharmony_ci		if ((_dst)->lags[(_id) - 1])
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci#define dsa_lag_foreach_port(_dp, _dst, _lag)			\
17362306a36Sopenharmony_ci	list_for_each_entry((_dp), &(_dst)->ports, list)	\
17462306a36Sopenharmony_ci		if (dsa_port_offloads_lag((_dp), (_lag)))
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci#define dsa_hsr_foreach_port(_dp, _ds, _hsr)			\
17762306a36Sopenharmony_ci	list_for_each_entry((_dp), &(_ds)->dst->ports, list)	\
17862306a36Sopenharmony_ci		if ((_dp)->ds == (_ds) && (_dp)->hsr_dev == (_hsr))
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_cistatic inline struct dsa_lag *dsa_lag_by_id(struct dsa_switch_tree *dst,
18162306a36Sopenharmony_ci					    unsigned int id)
18262306a36Sopenharmony_ci{
18362306a36Sopenharmony_ci	/* DSA LAG IDs are one-based, dst->lags is zero-based */
18462306a36Sopenharmony_ci	return dst->lags[id - 1];
18562306a36Sopenharmony_ci}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_cistatic inline int dsa_lag_id(struct dsa_switch_tree *dst,
18862306a36Sopenharmony_ci			     struct net_device *lag_dev)
18962306a36Sopenharmony_ci{
19062306a36Sopenharmony_ci	unsigned int id;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	dsa_lags_foreach_id(id, dst) {
19362306a36Sopenharmony_ci		struct dsa_lag *lag = dsa_lag_by_id(dst, id);
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci		if (lag->dev == lag_dev)
19662306a36Sopenharmony_ci			return lag->id;
19762306a36Sopenharmony_ci	}
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	return -ENODEV;
20062306a36Sopenharmony_ci}
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci/* TC matchall action types */
20362306a36Sopenharmony_cienum dsa_port_mall_action_type {
20462306a36Sopenharmony_ci	DSA_PORT_MALL_MIRROR,
20562306a36Sopenharmony_ci	DSA_PORT_MALL_POLICER,
20662306a36Sopenharmony_ci};
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci/* TC mirroring entry */
20962306a36Sopenharmony_cistruct dsa_mall_mirror_tc_entry {
21062306a36Sopenharmony_ci	u8 to_local_port;
21162306a36Sopenharmony_ci	bool ingress;
21262306a36Sopenharmony_ci};
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci/* TC port policer entry */
21562306a36Sopenharmony_cistruct dsa_mall_policer_tc_entry {
21662306a36Sopenharmony_ci	u32 burst;
21762306a36Sopenharmony_ci	u64 rate_bytes_per_sec;
21862306a36Sopenharmony_ci};
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci/* TC matchall entry */
22162306a36Sopenharmony_cistruct dsa_mall_tc_entry {
22262306a36Sopenharmony_ci	struct list_head list;
22362306a36Sopenharmony_ci	unsigned long cookie;
22462306a36Sopenharmony_ci	enum dsa_port_mall_action_type type;
22562306a36Sopenharmony_ci	union {
22662306a36Sopenharmony_ci		struct dsa_mall_mirror_tc_entry mirror;
22762306a36Sopenharmony_ci		struct dsa_mall_policer_tc_entry policer;
22862306a36Sopenharmony_ci	};
22962306a36Sopenharmony_ci};
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_cistruct dsa_bridge {
23262306a36Sopenharmony_ci	struct net_device *dev;
23362306a36Sopenharmony_ci	unsigned int num;
23462306a36Sopenharmony_ci	bool tx_fwd_offload;
23562306a36Sopenharmony_ci	refcount_t refcount;
23662306a36Sopenharmony_ci};
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cistruct dsa_port {
23962306a36Sopenharmony_ci	/* A CPU port is physically connected to a master device.
24062306a36Sopenharmony_ci	 * A user port exposed to userspace has a slave device.
24162306a36Sopenharmony_ci	 */
24262306a36Sopenharmony_ci	union {
24362306a36Sopenharmony_ci		struct net_device *master;
24462306a36Sopenharmony_ci		struct net_device *slave;
24562306a36Sopenharmony_ci	};
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	/* Copy of the tagging protocol operations, for quicker access
24862306a36Sopenharmony_ci	 * in the data path. Valid only for the CPU ports.
24962306a36Sopenharmony_ci	 */
25062306a36Sopenharmony_ci	const struct dsa_device_ops *tag_ops;
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	/* Copies for faster access in master receive hot path */
25362306a36Sopenharmony_ci	struct dsa_switch_tree *dst;
25462306a36Sopenharmony_ci	struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev);
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	struct dsa_switch	*ds;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	unsigned int		index;
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	enum {
26162306a36Sopenharmony_ci		DSA_PORT_TYPE_UNUSED = 0,
26262306a36Sopenharmony_ci		DSA_PORT_TYPE_CPU,
26362306a36Sopenharmony_ci		DSA_PORT_TYPE_DSA,
26462306a36Sopenharmony_ci		DSA_PORT_TYPE_USER,
26562306a36Sopenharmony_ci	} type;
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	const char		*name;
26862306a36Sopenharmony_ci	struct dsa_port		*cpu_dp;
26962306a36Sopenharmony_ci	u8			mac[ETH_ALEN];
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	u8			stp_state;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	/* Warning: the following bit fields are not atomic, and updating them
27462306a36Sopenharmony_ci	 * can only be done from code paths where concurrency is not possible
27562306a36Sopenharmony_ci	 * (probe time or under rtnl_lock).
27662306a36Sopenharmony_ci	 */
27762306a36Sopenharmony_ci	u8			vlan_filtering:1;
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	/* Managed by DSA on user ports and by drivers on CPU and DSA ports */
28062306a36Sopenharmony_ci	u8			learning:1;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	u8			lag_tx_enabled:1;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	/* Master state bits, valid only on CPU ports */
28562306a36Sopenharmony_ci	u8			master_admin_up:1;
28662306a36Sopenharmony_ci	u8			master_oper_up:1;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	/* Valid only on user ports */
28962306a36Sopenharmony_ci	u8			cpu_port_in_lag:1;
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	u8			setup:1;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	struct device_node	*dn;
29462306a36Sopenharmony_ci	unsigned int		ageing_time;
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	struct dsa_bridge	*bridge;
29762306a36Sopenharmony_ci	struct devlink_port	devlink_port;
29862306a36Sopenharmony_ci	struct phylink		*pl;
29962306a36Sopenharmony_ci	struct phylink_config	pl_config;
30062306a36Sopenharmony_ci	struct dsa_lag		*lag;
30162306a36Sopenharmony_ci	struct net_device	*hsr_dev;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	struct list_head list;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	/*
30662306a36Sopenharmony_ci	 * Original copy of the master netdev ethtool_ops
30762306a36Sopenharmony_ci	 */
30862306a36Sopenharmony_ci	const struct ethtool_ops *orig_ethtool_ops;
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	/* List of MAC addresses that must be forwarded on this port.
31162306a36Sopenharmony_ci	 * These are only valid on CPU ports and DSA links.
31262306a36Sopenharmony_ci	 */
31362306a36Sopenharmony_ci	struct mutex		addr_lists_lock;
31462306a36Sopenharmony_ci	struct list_head	fdbs;
31562306a36Sopenharmony_ci	struct list_head	mdbs;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	struct mutex		vlans_lock;
31862306a36Sopenharmony_ci	union {
31962306a36Sopenharmony_ci		/* List of VLANs that CPU and DSA ports are members of.
32062306a36Sopenharmony_ci		 * Access to this is serialized by the sleepable @vlans_lock.
32162306a36Sopenharmony_ci		 */
32262306a36Sopenharmony_ci		struct list_head	vlans;
32362306a36Sopenharmony_ci		/* List of VLANs that user ports are members of.
32462306a36Sopenharmony_ci		 * Access to this is serialized by netif_addr_lock_bh().
32562306a36Sopenharmony_ci		 */
32662306a36Sopenharmony_ci		struct list_head	user_vlans;
32762306a36Sopenharmony_ci	};
32862306a36Sopenharmony_ci};
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci/* TODO: ideally DSA ports would have a single dp->link_dp member,
33162306a36Sopenharmony_ci * and no dst->rtable nor this struct dsa_link would be needed,
33262306a36Sopenharmony_ci * but this would require some more complex tree walking,
33362306a36Sopenharmony_ci * so keep it stupid at the moment and list them all.
33462306a36Sopenharmony_ci */
33562306a36Sopenharmony_cistruct dsa_link {
33662306a36Sopenharmony_ci	struct dsa_port *dp;
33762306a36Sopenharmony_ci	struct dsa_port *link_dp;
33862306a36Sopenharmony_ci	struct list_head list;
33962306a36Sopenharmony_ci};
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_cienum dsa_db_type {
34262306a36Sopenharmony_ci	DSA_DB_PORT,
34362306a36Sopenharmony_ci	DSA_DB_LAG,
34462306a36Sopenharmony_ci	DSA_DB_BRIDGE,
34562306a36Sopenharmony_ci};
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_cistruct dsa_db {
34862306a36Sopenharmony_ci	enum dsa_db_type type;
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	union {
35162306a36Sopenharmony_ci		const struct dsa_port *dp;
35262306a36Sopenharmony_ci		struct dsa_lag lag;
35362306a36Sopenharmony_ci		struct dsa_bridge bridge;
35462306a36Sopenharmony_ci	};
35562306a36Sopenharmony_ci};
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_cistruct dsa_mac_addr {
35862306a36Sopenharmony_ci	unsigned char addr[ETH_ALEN];
35962306a36Sopenharmony_ci	u16 vid;
36062306a36Sopenharmony_ci	refcount_t refcount;
36162306a36Sopenharmony_ci	struct list_head list;
36262306a36Sopenharmony_ci	struct dsa_db db;
36362306a36Sopenharmony_ci};
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_cistruct dsa_vlan {
36662306a36Sopenharmony_ci	u16 vid;
36762306a36Sopenharmony_ci	refcount_t refcount;
36862306a36Sopenharmony_ci	struct list_head list;
36962306a36Sopenharmony_ci};
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_cistruct dsa_switch {
37262306a36Sopenharmony_ci	struct device *dev;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	/*
37562306a36Sopenharmony_ci	 * Parent switch tree, and switch index.
37662306a36Sopenharmony_ci	 */
37762306a36Sopenharmony_ci	struct dsa_switch_tree	*dst;
37862306a36Sopenharmony_ci	unsigned int		index;
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	/* Warning: the following bit fields are not atomic, and updating them
38162306a36Sopenharmony_ci	 * can only be done from code paths where concurrency is not possible
38262306a36Sopenharmony_ci	 * (probe time or under rtnl_lock).
38362306a36Sopenharmony_ci	 */
38462306a36Sopenharmony_ci	u32			setup:1;
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	/* Disallow bridge core from requesting different VLAN awareness
38762306a36Sopenharmony_ci	 * settings on ports if not hardware-supported
38862306a36Sopenharmony_ci	 */
38962306a36Sopenharmony_ci	u32			vlan_filtering_is_global:1;
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	/* Keep VLAN filtering enabled on ports not offloading any upper */
39262306a36Sopenharmony_ci	u32			needs_standalone_vlan_filtering:1;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	/* Pass .port_vlan_add and .port_vlan_del to drivers even for bridges
39562306a36Sopenharmony_ci	 * that have vlan_filtering=0. All drivers should ideally set this (and
39662306a36Sopenharmony_ci	 * then the option would get removed), but it is unknown whether this
39762306a36Sopenharmony_ci	 * would break things or not.
39862306a36Sopenharmony_ci	 */
39962306a36Sopenharmony_ci	u32			configure_vlan_while_not_filtering:1;
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	/* If the switch driver always programs the CPU port as egress tagged
40262306a36Sopenharmony_ci	 * despite the VLAN configuration indicating otherwise, then setting
40362306a36Sopenharmony_ci	 * @untag_bridge_pvid will force the DSA receive path to pop the
40462306a36Sopenharmony_ci	 * bridge's default_pvid VLAN tagged frames to offer a consistent
40562306a36Sopenharmony_ci	 * behavior between a vlan_filtering=0 and vlan_filtering=1 bridge
40662306a36Sopenharmony_ci	 * device.
40762306a36Sopenharmony_ci	 */
40862306a36Sopenharmony_ci	u32			untag_bridge_pvid:1;
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	/* Let DSA manage the FDB entries towards the
41162306a36Sopenharmony_ci	 * CPU, based on the software bridge database.
41262306a36Sopenharmony_ci	 */
41362306a36Sopenharmony_ci	u32			assisted_learning_on_cpu_port:1;
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	/* In case vlan_filtering_is_global is set, the VLAN awareness state
41662306a36Sopenharmony_ci	 * should be retrieved from here and not from the per-port settings.
41762306a36Sopenharmony_ci	 */
41862306a36Sopenharmony_ci	u32			vlan_filtering:1;
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	/* For switches that only have the MRU configurable. To ensure the
42162306a36Sopenharmony_ci	 * configured MTU is not exceeded, normalization of MRU on all bridged
42262306a36Sopenharmony_ci	 * interfaces is needed.
42362306a36Sopenharmony_ci	 */
42462306a36Sopenharmony_ci	u32			mtu_enforcement_ingress:1;
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	/* Drivers that isolate the FDBs of multiple bridges must set this
42762306a36Sopenharmony_ci	 * to true to receive the bridge as an argument in .port_fdb_{add,del}
42862306a36Sopenharmony_ci	 * and .port_mdb_{add,del}. Otherwise, the bridge.num will always be
42962306a36Sopenharmony_ci	 * passed as zero.
43062306a36Sopenharmony_ci	 */
43162306a36Sopenharmony_ci	u32			fdb_isolation:1;
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	/* Listener for switch fabric events */
43462306a36Sopenharmony_ci	struct notifier_block	nb;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	/*
43762306a36Sopenharmony_ci	 * Give the switch driver somewhere to hang its private data
43862306a36Sopenharmony_ci	 * structure.
43962306a36Sopenharmony_ci	 */
44062306a36Sopenharmony_ci	void *priv;
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci	void *tagger_data;
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	/*
44562306a36Sopenharmony_ci	 * Configuration data for this switch.
44662306a36Sopenharmony_ci	 */
44762306a36Sopenharmony_ci	struct dsa_chip_data	*cd;
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci	/*
45062306a36Sopenharmony_ci	 * The switch operations.
45162306a36Sopenharmony_ci	 */
45262306a36Sopenharmony_ci	const struct dsa_switch_ops	*ops;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	/*
45562306a36Sopenharmony_ci	 * Slave mii_bus and devices for the individual ports.
45662306a36Sopenharmony_ci	 */
45762306a36Sopenharmony_ci	u32			phys_mii_mask;
45862306a36Sopenharmony_ci	struct mii_bus		*slave_mii_bus;
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	/* Ageing Time limits in msecs */
46162306a36Sopenharmony_ci	unsigned int ageing_time_min;
46262306a36Sopenharmony_ci	unsigned int ageing_time_max;
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	/* Storage for drivers using tag_8021q */
46562306a36Sopenharmony_ci	struct dsa_8021q_context *tag_8021q_ctx;
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	/* devlink used to represent this switch device */
46862306a36Sopenharmony_ci	struct devlink		*devlink;
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	/* Number of switch port queues */
47162306a36Sopenharmony_ci	unsigned int		num_tx_queues;
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	/* Drivers that benefit from having an ID associated with each
47462306a36Sopenharmony_ci	 * offloaded LAG should set this to the maximum number of
47562306a36Sopenharmony_ci	 * supported IDs. DSA will then maintain a mapping of _at
47662306a36Sopenharmony_ci	 * least_ these many IDs, accessible to drivers via
47762306a36Sopenharmony_ci	 * dsa_lag_id().
47862306a36Sopenharmony_ci	 */
47962306a36Sopenharmony_ci	unsigned int		num_lag_ids;
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	/* Drivers that support bridge forwarding offload or FDB isolation
48262306a36Sopenharmony_ci	 * should set this to the maximum number of bridges spanning the same
48362306a36Sopenharmony_ci	 * switch tree (or all trees, in the case of cross-tree bridging
48462306a36Sopenharmony_ci	 * support) that can be offloaded.
48562306a36Sopenharmony_ci	 */
48662306a36Sopenharmony_ci	unsigned int		max_num_bridges;
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci	unsigned int		num_ports;
48962306a36Sopenharmony_ci};
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_cistatic inline struct dsa_port *dsa_to_port(struct dsa_switch *ds, int p)
49262306a36Sopenharmony_ci{
49362306a36Sopenharmony_ci	struct dsa_switch_tree *dst = ds->dst;
49462306a36Sopenharmony_ci	struct dsa_port *dp;
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	list_for_each_entry(dp, &dst->ports, list)
49762306a36Sopenharmony_ci		if (dp->ds == ds && dp->index == p)
49862306a36Sopenharmony_ci			return dp;
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	return NULL;
50162306a36Sopenharmony_ci}
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_cistatic inline bool dsa_port_is_dsa(struct dsa_port *port)
50462306a36Sopenharmony_ci{
50562306a36Sopenharmony_ci	return port->type == DSA_PORT_TYPE_DSA;
50662306a36Sopenharmony_ci}
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_cistatic inline bool dsa_port_is_cpu(struct dsa_port *port)
50962306a36Sopenharmony_ci{
51062306a36Sopenharmony_ci	return port->type == DSA_PORT_TYPE_CPU;
51162306a36Sopenharmony_ci}
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_cistatic inline bool dsa_port_is_user(struct dsa_port *dp)
51462306a36Sopenharmony_ci{
51562306a36Sopenharmony_ci	return dp->type == DSA_PORT_TYPE_USER;
51662306a36Sopenharmony_ci}
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_cistatic inline bool dsa_port_is_unused(struct dsa_port *dp)
51962306a36Sopenharmony_ci{
52062306a36Sopenharmony_ci	return dp->type == DSA_PORT_TYPE_UNUSED;
52162306a36Sopenharmony_ci}
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_cistatic inline bool dsa_port_master_is_operational(struct dsa_port *dp)
52462306a36Sopenharmony_ci{
52562306a36Sopenharmony_ci	return dsa_port_is_cpu(dp) && dp->master_admin_up &&
52662306a36Sopenharmony_ci	       dp->master_oper_up;
52762306a36Sopenharmony_ci}
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_cistatic inline bool dsa_is_unused_port(struct dsa_switch *ds, int p)
53062306a36Sopenharmony_ci{
53162306a36Sopenharmony_ci	return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_UNUSED;
53262306a36Sopenharmony_ci}
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_cistatic inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p)
53562306a36Sopenharmony_ci{
53662306a36Sopenharmony_ci	return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_CPU;
53762306a36Sopenharmony_ci}
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_cistatic inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p)
54062306a36Sopenharmony_ci{
54162306a36Sopenharmony_ci	return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_DSA;
54262306a36Sopenharmony_ci}
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_cistatic inline bool dsa_is_user_port(struct dsa_switch *ds, int p)
54562306a36Sopenharmony_ci{
54662306a36Sopenharmony_ci	return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_USER;
54762306a36Sopenharmony_ci}
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci#define dsa_tree_for_each_user_port(_dp, _dst) \
55062306a36Sopenharmony_ci	list_for_each_entry((_dp), &(_dst)->ports, list) \
55162306a36Sopenharmony_ci		if (dsa_port_is_user((_dp)))
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci#define dsa_tree_for_each_user_port_continue_reverse(_dp, _dst) \
55462306a36Sopenharmony_ci	list_for_each_entry_continue_reverse((_dp), &(_dst)->ports, list) \
55562306a36Sopenharmony_ci		if (dsa_port_is_user((_dp)))
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci#define dsa_tree_for_each_cpu_port(_dp, _dst) \
55862306a36Sopenharmony_ci	list_for_each_entry((_dp), &(_dst)->ports, list) \
55962306a36Sopenharmony_ci		if (dsa_port_is_cpu((_dp)))
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci#define dsa_switch_for_each_port(_dp, _ds) \
56262306a36Sopenharmony_ci	list_for_each_entry((_dp), &(_ds)->dst->ports, list) \
56362306a36Sopenharmony_ci		if ((_dp)->ds == (_ds))
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci#define dsa_switch_for_each_port_safe(_dp, _next, _ds) \
56662306a36Sopenharmony_ci	list_for_each_entry_safe((_dp), (_next), &(_ds)->dst->ports, list) \
56762306a36Sopenharmony_ci		if ((_dp)->ds == (_ds))
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci#define dsa_switch_for_each_port_continue_reverse(_dp, _ds) \
57062306a36Sopenharmony_ci	list_for_each_entry_continue_reverse((_dp), &(_ds)->dst->ports, list) \
57162306a36Sopenharmony_ci		if ((_dp)->ds == (_ds))
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci#define dsa_switch_for_each_available_port(_dp, _ds) \
57462306a36Sopenharmony_ci	dsa_switch_for_each_port((_dp), (_ds)) \
57562306a36Sopenharmony_ci		if (!dsa_port_is_unused((_dp)))
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci#define dsa_switch_for_each_user_port(_dp, _ds) \
57862306a36Sopenharmony_ci	dsa_switch_for_each_port((_dp), (_ds)) \
57962306a36Sopenharmony_ci		if (dsa_port_is_user((_dp)))
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci#define dsa_switch_for_each_cpu_port(_dp, _ds) \
58262306a36Sopenharmony_ci	dsa_switch_for_each_port((_dp), (_ds)) \
58362306a36Sopenharmony_ci		if (dsa_port_is_cpu((_dp)))
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci#define dsa_switch_for_each_cpu_port_continue_reverse(_dp, _ds) \
58662306a36Sopenharmony_ci	dsa_switch_for_each_port_continue_reverse((_dp), (_ds)) \
58762306a36Sopenharmony_ci		if (dsa_port_is_cpu((_dp)))
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_cistatic inline u32 dsa_user_ports(struct dsa_switch *ds)
59062306a36Sopenharmony_ci{
59162306a36Sopenharmony_ci	struct dsa_port *dp;
59262306a36Sopenharmony_ci	u32 mask = 0;
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	dsa_switch_for_each_user_port(dp, ds)
59562306a36Sopenharmony_ci		mask |= BIT(dp->index);
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	return mask;
59862306a36Sopenharmony_ci}
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_cistatic inline u32 dsa_cpu_ports(struct dsa_switch *ds)
60162306a36Sopenharmony_ci{
60262306a36Sopenharmony_ci	struct dsa_port *cpu_dp;
60362306a36Sopenharmony_ci	u32 mask = 0;
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci	dsa_switch_for_each_cpu_port(cpu_dp, ds)
60662306a36Sopenharmony_ci		mask |= BIT(cpu_dp->index);
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	return mask;
60962306a36Sopenharmony_ci}
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci/* Return the local port used to reach an arbitrary switch device */
61262306a36Sopenharmony_cistatic inline unsigned int dsa_routing_port(struct dsa_switch *ds, int device)
61362306a36Sopenharmony_ci{
61462306a36Sopenharmony_ci	struct dsa_switch_tree *dst = ds->dst;
61562306a36Sopenharmony_ci	struct dsa_link *dl;
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	list_for_each_entry(dl, &dst->rtable, list)
61862306a36Sopenharmony_ci		if (dl->dp->ds == ds && dl->link_dp->ds->index == device)
61962306a36Sopenharmony_ci			return dl->dp->index;
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci	return ds->num_ports;
62262306a36Sopenharmony_ci}
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ci/* Return the local port used to reach an arbitrary switch port */
62562306a36Sopenharmony_cistatic inline unsigned int dsa_towards_port(struct dsa_switch *ds, int device,
62662306a36Sopenharmony_ci					    int port)
62762306a36Sopenharmony_ci{
62862306a36Sopenharmony_ci	if (device == ds->index)
62962306a36Sopenharmony_ci		return port;
63062306a36Sopenharmony_ci	else
63162306a36Sopenharmony_ci		return dsa_routing_port(ds, device);
63262306a36Sopenharmony_ci}
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci/* Return the local port used to reach the dedicated CPU port */
63562306a36Sopenharmony_cistatic inline unsigned int dsa_upstream_port(struct dsa_switch *ds, int port)
63662306a36Sopenharmony_ci{
63762306a36Sopenharmony_ci	const struct dsa_port *dp = dsa_to_port(ds, port);
63862306a36Sopenharmony_ci	const struct dsa_port *cpu_dp = dp->cpu_dp;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci	if (!cpu_dp)
64162306a36Sopenharmony_ci		return port;
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	return dsa_towards_port(ds, cpu_dp->ds->index, cpu_dp->index);
64462306a36Sopenharmony_ci}
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci/* Return true if this is the local port used to reach the CPU port */
64762306a36Sopenharmony_cistatic inline bool dsa_is_upstream_port(struct dsa_switch *ds, int port)
64862306a36Sopenharmony_ci{
64962306a36Sopenharmony_ci	if (dsa_is_unused_port(ds, port))
65062306a36Sopenharmony_ci		return false;
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	return port == dsa_upstream_port(ds, port);
65362306a36Sopenharmony_ci}
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci/* Return true if this is a DSA port leading away from the CPU */
65662306a36Sopenharmony_cistatic inline bool dsa_is_downstream_port(struct dsa_switch *ds, int port)
65762306a36Sopenharmony_ci{
65862306a36Sopenharmony_ci	return dsa_is_dsa_port(ds, port) && !dsa_is_upstream_port(ds, port);
65962306a36Sopenharmony_ci}
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci/* Return the local port used to reach the CPU port */
66262306a36Sopenharmony_cistatic inline unsigned int dsa_switch_upstream_port(struct dsa_switch *ds)
66362306a36Sopenharmony_ci{
66462306a36Sopenharmony_ci	struct dsa_port *dp;
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	dsa_switch_for_each_available_port(dp, ds) {
66762306a36Sopenharmony_ci		return dsa_upstream_port(ds, dp->index);
66862306a36Sopenharmony_ci	}
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	return ds->num_ports;
67162306a36Sopenharmony_ci}
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci/* Return true if @upstream_ds is an upstream switch of @downstream_ds, meaning
67462306a36Sopenharmony_ci * that the routing port from @downstream_ds to @upstream_ds is also the port
67562306a36Sopenharmony_ci * which @downstream_ds uses to reach its dedicated CPU.
67662306a36Sopenharmony_ci */
67762306a36Sopenharmony_cistatic inline bool dsa_switch_is_upstream_of(struct dsa_switch *upstream_ds,
67862306a36Sopenharmony_ci					     struct dsa_switch *downstream_ds)
67962306a36Sopenharmony_ci{
68062306a36Sopenharmony_ci	int routing_port;
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	if (upstream_ds == downstream_ds)
68362306a36Sopenharmony_ci		return true;
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	routing_port = dsa_routing_port(downstream_ds, upstream_ds->index);
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci	return dsa_is_upstream_port(downstream_ds, routing_port);
68862306a36Sopenharmony_ci}
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_cistatic inline bool dsa_port_is_vlan_filtering(const struct dsa_port *dp)
69162306a36Sopenharmony_ci{
69262306a36Sopenharmony_ci	const struct dsa_switch *ds = dp->ds;
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci	if (ds->vlan_filtering_is_global)
69562306a36Sopenharmony_ci		return ds->vlan_filtering;
69662306a36Sopenharmony_ci	else
69762306a36Sopenharmony_ci		return dp->vlan_filtering;
69862306a36Sopenharmony_ci}
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_cistatic inline unsigned int dsa_port_lag_id_get(struct dsa_port *dp)
70162306a36Sopenharmony_ci{
70262306a36Sopenharmony_ci	return dp->lag ? dp->lag->id : 0;
70362306a36Sopenharmony_ci}
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_cistatic inline struct net_device *dsa_port_lag_dev_get(struct dsa_port *dp)
70662306a36Sopenharmony_ci{
70762306a36Sopenharmony_ci	return dp->lag ? dp->lag->dev : NULL;
70862306a36Sopenharmony_ci}
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_cistatic inline bool dsa_port_offloads_lag(struct dsa_port *dp,
71162306a36Sopenharmony_ci					 const struct dsa_lag *lag)
71262306a36Sopenharmony_ci{
71362306a36Sopenharmony_ci	return dsa_port_lag_dev_get(dp) == lag->dev;
71462306a36Sopenharmony_ci}
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_cistatic inline struct net_device *dsa_port_to_master(const struct dsa_port *dp)
71762306a36Sopenharmony_ci{
71862306a36Sopenharmony_ci	if (dp->cpu_port_in_lag)
71962306a36Sopenharmony_ci		return dsa_port_lag_dev_get(dp->cpu_dp);
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci	return dp->cpu_dp->master;
72262306a36Sopenharmony_ci}
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_cistatic inline
72562306a36Sopenharmony_cistruct net_device *dsa_port_to_bridge_port(const struct dsa_port *dp)
72662306a36Sopenharmony_ci{
72762306a36Sopenharmony_ci	if (!dp->bridge)
72862306a36Sopenharmony_ci		return NULL;
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_ci	if (dp->lag)
73162306a36Sopenharmony_ci		return dp->lag->dev;
73262306a36Sopenharmony_ci	else if (dp->hsr_dev)
73362306a36Sopenharmony_ci		return dp->hsr_dev;
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci	return dp->slave;
73662306a36Sopenharmony_ci}
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_cistatic inline struct net_device *
73962306a36Sopenharmony_cidsa_port_bridge_dev_get(const struct dsa_port *dp)
74062306a36Sopenharmony_ci{
74162306a36Sopenharmony_ci	return dp->bridge ? dp->bridge->dev : NULL;
74262306a36Sopenharmony_ci}
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_cistatic inline unsigned int dsa_port_bridge_num_get(struct dsa_port *dp)
74562306a36Sopenharmony_ci{
74662306a36Sopenharmony_ci	return dp->bridge ? dp->bridge->num : 0;
74762306a36Sopenharmony_ci}
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_cistatic inline bool dsa_port_bridge_same(const struct dsa_port *a,
75062306a36Sopenharmony_ci					const struct dsa_port *b)
75162306a36Sopenharmony_ci{
75262306a36Sopenharmony_ci	struct net_device *br_a = dsa_port_bridge_dev_get(a);
75362306a36Sopenharmony_ci	struct net_device *br_b = dsa_port_bridge_dev_get(b);
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci	/* Standalone ports are not in the same bridge with one another */
75662306a36Sopenharmony_ci	return (!br_a || !br_b) ? false : (br_a == br_b);
75762306a36Sopenharmony_ci}
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_cistatic inline bool dsa_port_offloads_bridge_port(struct dsa_port *dp,
76062306a36Sopenharmony_ci						 const struct net_device *dev)
76162306a36Sopenharmony_ci{
76262306a36Sopenharmony_ci	return dsa_port_to_bridge_port(dp) == dev;
76362306a36Sopenharmony_ci}
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_cistatic inline bool
76662306a36Sopenharmony_cidsa_port_offloads_bridge_dev(struct dsa_port *dp,
76762306a36Sopenharmony_ci			     const struct net_device *bridge_dev)
76862306a36Sopenharmony_ci{
76962306a36Sopenharmony_ci	/* DSA ports connected to a bridge, and event was emitted
77062306a36Sopenharmony_ci	 * for the bridge.
77162306a36Sopenharmony_ci	 */
77262306a36Sopenharmony_ci	return dsa_port_bridge_dev_get(dp) == bridge_dev;
77362306a36Sopenharmony_ci}
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_cistatic inline bool dsa_port_offloads_bridge(struct dsa_port *dp,
77662306a36Sopenharmony_ci					    const struct dsa_bridge *bridge)
77762306a36Sopenharmony_ci{
77862306a36Sopenharmony_ci	return dsa_port_bridge_dev_get(dp) == bridge->dev;
77962306a36Sopenharmony_ci}
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_ci/* Returns true if any port of this tree offloads the given net_device */
78262306a36Sopenharmony_cistatic inline bool dsa_tree_offloads_bridge_port(struct dsa_switch_tree *dst,
78362306a36Sopenharmony_ci						 const struct net_device *dev)
78462306a36Sopenharmony_ci{
78562306a36Sopenharmony_ci	struct dsa_port *dp;
78662306a36Sopenharmony_ci
78762306a36Sopenharmony_ci	list_for_each_entry(dp, &dst->ports, list)
78862306a36Sopenharmony_ci		if (dsa_port_offloads_bridge_port(dp, dev))
78962306a36Sopenharmony_ci			return true;
79062306a36Sopenharmony_ci
79162306a36Sopenharmony_ci	return false;
79262306a36Sopenharmony_ci}
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci/* Returns true if any port of this tree offloads the given bridge */
79562306a36Sopenharmony_cistatic inline bool
79662306a36Sopenharmony_cidsa_tree_offloads_bridge_dev(struct dsa_switch_tree *dst,
79762306a36Sopenharmony_ci			     const struct net_device *bridge_dev)
79862306a36Sopenharmony_ci{
79962306a36Sopenharmony_ci	struct dsa_port *dp;
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci	list_for_each_entry(dp, &dst->ports, list)
80262306a36Sopenharmony_ci		if (dsa_port_offloads_bridge_dev(dp, bridge_dev))
80362306a36Sopenharmony_ci			return true;
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci	return false;
80662306a36Sopenharmony_ci}
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_cistatic inline bool dsa_port_tree_same(const struct dsa_port *a,
80962306a36Sopenharmony_ci				      const struct dsa_port *b)
81062306a36Sopenharmony_ci{
81162306a36Sopenharmony_ci	return a->ds->dst == b->ds->dst;
81262306a36Sopenharmony_ci}
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_citypedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid,
81562306a36Sopenharmony_ci			      bool is_static, void *data);
81662306a36Sopenharmony_cistruct dsa_switch_ops {
81762306a36Sopenharmony_ci	/*
81862306a36Sopenharmony_ci	 * Tagging protocol helpers called for the CPU ports and DSA links.
81962306a36Sopenharmony_ci	 * @get_tag_protocol retrieves the initial tagging protocol and is
82062306a36Sopenharmony_ci	 * mandatory. Switches which can operate using multiple tagging
82162306a36Sopenharmony_ci	 * protocols should implement @change_tag_protocol and report in
82262306a36Sopenharmony_ci	 * @get_tag_protocol the tagger in current use.
82362306a36Sopenharmony_ci	 */
82462306a36Sopenharmony_ci	enum dsa_tag_protocol (*get_tag_protocol)(struct dsa_switch *ds,
82562306a36Sopenharmony_ci						  int port,
82662306a36Sopenharmony_ci						  enum dsa_tag_protocol mprot);
82762306a36Sopenharmony_ci	int	(*change_tag_protocol)(struct dsa_switch *ds,
82862306a36Sopenharmony_ci				       enum dsa_tag_protocol proto);
82962306a36Sopenharmony_ci	/*
83062306a36Sopenharmony_ci	 * Method for switch drivers to connect to the tagging protocol driver
83162306a36Sopenharmony_ci	 * in current use. The switch driver can provide handlers for certain
83262306a36Sopenharmony_ci	 * types of packets for switch management.
83362306a36Sopenharmony_ci	 */
83462306a36Sopenharmony_ci	int	(*connect_tag_protocol)(struct dsa_switch *ds,
83562306a36Sopenharmony_ci					enum dsa_tag_protocol proto);
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	int	(*port_change_master)(struct dsa_switch *ds, int port,
83862306a36Sopenharmony_ci				      struct net_device *master,
83962306a36Sopenharmony_ci				      struct netlink_ext_ack *extack);
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci	/* Optional switch-wide initialization and destruction methods */
84262306a36Sopenharmony_ci	int	(*setup)(struct dsa_switch *ds);
84362306a36Sopenharmony_ci	void	(*teardown)(struct dsa_switch *ds);
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_ci	/* Per-port initialization and destruction methods. Mandatory if the
84662306a36Sopenharmony_ci	 * driver registers devlink port regions, optional otherwise.
84762306a36Sopenharmony_ci	 */
84862306a36Sopenharmony_ci	int	(*port_setup)(struct dsa_switch *ds, int port);
84962306a36Sopenharmony_ci	void	(*port_teardown)(struct dsa_switch *ds, int port);
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci	u32	(*get_phy_flags)(struct dsa_switch *ds, int port);
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	/*
85462306a36Sopenharmony_ci	 * Access to the switch's PHY registers.
85562306a36Sopenharmony_ci	 */
85662306a36Sopenharmony_ci	int	(*phy_read)(struct dsa_switch *ds, int port, int regnum);
85762306a36Sopenharmony_ci	int	(*phy_write)(struct dsa_switch *ds, int port,
85862306a36Sopenharmony_ci			     int regnum, u16 val);
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci	/*
86162306a36Sopenharmony_ci	 * Link state adjustment (called from libphy)
86262306a36Sopenharmony_ci	 */
86362306a36Sopenharmony_ci	void	(*adjust_link)(struct dsa_switch *ds, int port,
86462306a36Sopenharmony_ci				struct phy_device *phydev);
86562306a36Sopenharmony_ci	void	(*fixed_link_update)(struct dsa_switch *ds, int port,
86662306a36Sopenharmony_ci				struct fixed_phy_status *st);
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci	/*
86962306a36Sopenharmony_ci	 * PHYLINK integration
87062306a36Sopenharmony_ci	 */
87162306a36Sopenharmony_ci	void	(*phylink_get_caps)(struct dsa_switch *ds, int port,
87262306a36Sopenharmony_ci				    struct phylink_config *config);
87362306a36Sopenharmony_ci	struct phylink_pcs *(*phylink_mac_select_pcs)(struct dsa_switch *ds,
87462306a36Sopenharmony_ci						      int port,
87562306a36Sopenharmony_ci						      phy_interface_t iface);
87662306a36Sopenharmony_ci	int	(*phylink_mac_prepare)(struct dsa_switch *ds, int port,
87762306a36Sopenharmony_ci				       unsigned int mode,
87862306a36Sopenharmony_ci				       phy_interface_t interface);
87962306a36Sopenharmony_ci	void	(*phylink_mac_config)(struct dsa_switch *ds, int port,
88062306a36Sopenharmony_ci				      unsigned int mode,
88162306a36Sopenharmony_ci				      const struct phylink_link_state *state);
88262306a36Sopenharmony_ci	int	(*phylink_mac_finish)(struct dsa_switch *ds, int port,
88362306a36Sopenharmony_ci				      unsigned int mode,
88462306a36Sopenharmony_ci				      phy_interface_t interface);
88562306a36Sopenharmony_ci	void	(*phylink_mac_link_down)(struct dsa_switch *ds, int port,
88662306a36Sopenharmony_ci					 unsigned int mode,
88762306a36Sopenharmony_ci					 phy_interface_t interface);
88862306a36Sopenharmony_ci	void	(*phylink_mac_link_up)(struct dsa_switch *ds, int port,
88962306a36Sopenharmony_ci				       unsigned int mode,
89062306a36Sopenharmony_ci				       phy_interface_t interface,
89162306a36Sopenharmony_ci				       struct phy_device *phydev,
89262306a36Sopenharmony_ci				       int speed, int duplex,
89362306a36Sopenharmony_ci				       bool tx_pause, bool rx_pause);
89462306a36Sopenharmony_ci	void	(*phylink_fixed_state)(struct dsa_switch *ds, int port,
89562306a36Sopenharmony_ci				       struct phylink_link_state *state);
89662306a36Sopenharmony_ci	/*
89762306a36Sopenharmony_ci	 * Port statistics counters.
89862306a36Sopenharmony_ci	 */
89962306a36Sopenharmony_ci	void	(*get_strings)(struct dsa_switch *ds, int port,
90062306a36Sopenharmony_ci			       u32 stringset, uint8_t *data);
90162306a36Sopenharmony_ci	void	(*get_ethtool_stats)(struct dsa_switch *ds,
90262306a36Sopenharmony_ci				     int port, uint64_t *data);
90362306a36Sopenharmony_ci	int	(*get_sset_count)(struct dsa_switch *ds, int port, int sset);
90462306a36Sopenharmony_ci	void	(*get_ethtool_phy_stats)(struct dsa_switch *ds,
90562306a36Sopenharmony_ci					 int port, uint64_t *data);
90662306a36Sopenharmony_ci	void	(*get_eth_phy_stats)(struct dsa_switch *ds, int port,
90762306a36Sopenharmony_ci				     struct ethtool_eth_phy_stats *phy_stats);
90862306a36Sopenharmony_ci	void	(*get_eth_mac_stats)(struct dsa_switch *ds, int port,
90962306a36Sopenharmony_ci				     struct ethtool_eth_mac_stats *mac_stats);
91062306a36Sopenharmony_ci	void	(*get_eth_ctrl_stats)(struct dsa_switch *ds, int port,
91162306a36Sopenharmony_ci				      struct ethtool_eth_ctrl_stats *ctrl_stats);
91262306a36Sopenharmony_ci	void	(*get_rmon_stats)(struct dsa_switch *ds, int port,
91362306a36Sopenharmony_ci				  struct ethtool_rmon_stats *rmon_stats,
91462306a36Sopenharmony_ci				  const struct ethtool_rmon_hist_range **ranges);
91562306a36Sopenharmony_ci	void	(*get_stats64)(struct dsa_switch *ds, int port,
91662306a36Sopenharmony_ci				   struct rtnl_link_stats64 *s);
91762306a36Sopenharmony_ci	void	(*get_pause_stats)(struct dsa_switch *ds, int port,
91862306a36Sopenharmony_ci				   struct ethtool_pause_stats *pause_stats);
91962306a36Sopenharmony_ci	void	(*self_test)(struct dsa_switch *ds, int port,
92062306a36Sopenharmony_ci			     struct ethtool_test *etest, u64 *data);
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci	/*
92362306a36Sopenharmony_ci	 * ethtool Wake-on-LAN
92462306a36Sopenharmony_ci	 */
92562306a36Sopenharmony_ci	void	(*get_wol)(struct dsa_switch *ds, int port,
92662306a36Sopenharmony_ci			   struct ethtool_wolinfo *w);
92762306a36Sopenharmony_ci	int	(*set_wol)(struct dsa_switch *ds, int port,
92862306a36Sopenharmony_ci			   struct ethtool_wolinfo *w);
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ci	/*
93162306a36Sopenharmony_ci	 * ethtool timestamp info
93262306a36Sopenharmony_ci	 */
93362306a36Sopenharmony_ci	int	(*get_ts_info)(struct dsa_switch *ds, int port,
93462306a36Sopenharmony_ci			       struct ethtool_ts_info *ts);
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ci	/*
93762306a36Sopenharmony_ci	 * ethtool MAC merge layer
93862306a36Sopenharmony_ci	 */
93962306a36Sopenharmony_ci	int	(*get_mm)(struct dsa_switch *ds, int port,
94062306a36Sopenharmony_ci			  struct ethtool_mm_state *state);
94162306a36Sopenharmony_ci	int	(*set_mm)(struct dsa_switch *ds, int port,
94262306a36Sopenharmony_ci			  struct ethtool_mm_cfg *cfg,
94362306a36Sopenharmony_ci			  struct netlink_ext_ack *extack);
94462306a36Sopenharmony_ci	void	(*get_mm_stats)(struct dsa_switch *ds, int port,
94562306a36Sopenharmony_ci				struct ethtool_mm_stats *stats);
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci	/*
94862306a36Sopenharmony_ci	 * DCB ops
94962306a36Sopenharmony_ci	 */
95062306a36Sopenharmony_ci	int	(*port_get_default_prio)(struct dsa_switch *ds, int port);
95162306a36Sopenharmony_ci	int	(*port_set_default_prio)(struct dsa_switch *ds, int port,
95262306a36Sopenharmony_ci					 u8 prio);
95362306a36Sopenharmony_ci	int	(*port_get_dscp_prio)(struct dsa_switch *ds, int port, u8 dscp);
95462306a36Sopenharmony_ci	int	(*port_add_dscp_prio)(struct dsa_switch *ds, int port, u8 dscp,
95562306a36Sopenharmony_ci				      u8 prio);
95662306a36Sopenharmony_ci	int	(*port_del_dscp_prio)(struct dsa_switch *ds, int port, u8 dscp,
95762306a36Sopenharmony_ci				      u8 prio);
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci	/*
96062306a36Sopenharmony_ci	 * Suspend and resume
96162306a36Sopenharmony_ci	 */
96262306a36Sopenharmony_ci	int	(*suspend)(struct dsa_switch *ds);
96362306a36Sopenharmony_ci	int	(*resume)(struct dsa_switch *ds);
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	/*
96662306a36Sopenharmony_ci	 * Port enable/disable
96762306a36Sopenharmony_ci	 */
96862306a36Sopenharmony_ci	int	(*port_enable)(struct dsa_switch *ds, int port,
96962306a36Sopenharmony_ci			       struct phy_device *phy);
97062306a36Sopenharmony_ci	void	(*port_disable)(struct dsa_switch *ds, int port);
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci	/*
97362306a36Sopenharmony_ci	 * Compatibility between device trees defining multiple CPU ports and
97462306a36Sopenharmony_ci	 * drivers which are not OK to use by default the numerically smallest
97562306a36Sopenharmony_ci	 * CPU port of a switch for its local ports. This can return NULL,
97662306a36Sopenharmony_ci	 * meaning "don't know/don't care".
97762306a36Sopenharmony_ci	 */
97862306a36Sopenharmony_ci	struct dsa_port *(*preferred_default_local_cpu_port)(struct dsa_switch *ds);
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ci	/*
98162306a36Sopenharmony_ci	 * Port's MAC EEE settings
98262306a36Sopenharmony_ci	 */
98362306a36Sopenharmony_ci	int	(*set_mac_eee)(struct dsa_switch *ds, int port,
98462306a36Sopenharmony_ci			       struct ethtool_eee *e);
98562306a36Sopenharmony_ci	int	(*get_mac_eee)(struct dsa_switch *ds, int port,
98662306a36Sopenharmony_ci			       struct ethtool_eee *e);
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci	/* EEPROM access */
98962306a36Sopenharmony_ci	int	(*get_eeprom_len)(struct dsa_switch *ds);
99062306a36Sopenharmony_ci	int	(*get_eeprom)(struct dsa_switch *ds,
99162306a36Sopenharmony_ci			      struct ethtool_eeprom *eeprom, u8 *data);
99262306a36Sopenharmony_ci	int	(*set_eeprom)(struct dsa_switch *ds,
99362306a36Sopenharmony_ci			      struct ethtool_eeprom *eeprom, u8 *data);
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ci	/*
99662306a36Sopenharmony_ci	 * Register access.
99762306a36Sopenharmony_ci	 */
99862306a36Sopenharmony_ci	int	(*get_regs_len)(struct dsa_switch *ds, int port);
99962306a36Sopenharmony_ci	void	(*get_regs)(struct dsa_switch *ds, int port,
100062306a36Sopenharmony_ci			    struct ethtool_regs *regs, void *p);
100162306a36Sopenharmony_ci
100262306a36Sopenharmony_ci	/*
100362306a36Sopenharmony_ci	 * Upper device tracking.
100462306a36Sopenharmony_ci	 */
100562306a36Sopenharmony_ci	int	(*port_prechangeupper)(struct dsa_switch *ds, int port,
100662306a36Sopenharmony_ci				       struct netdev_notifier_changeupper_info *info);
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci	/*
100962306a36Sopenharmony_ci	 * Bridge integration
101062306a36Sopenharmony_ci	 */
101162306a36Sopenharmony_ci	int	(*set_ageing_time)(struct dsa_switch *ds, unsigned int msecs);
101262306a36Sopenharmony_ci	int	(*port_bridge_join)(struct dsa_switch *ds, int port,
101362306a36Sopenharmony_ci				    struct dsa_bridge bridge,
101462306a36Sopenharmony_ci				    bool *tx_fwd_offload,
101562306a36Sopenharmony_ci				    struct netlink_ext_ack *extack);
101662306a36Sopenharmony_ci	void	(*port_bridge_leave)(struct dsa_switch *ds, int port,
101762306a36Sopenharmony_ci				     struct dsa_bridge bridge);
101862306a36Sopenharmony_ci	void	(*port_stp_state_set)(struct dsa_switch *ds, int port,
101962306a36Sopenharmony_ci				      u8 state);
102062306a36Sopenharmony_ci	int	(*port_mst_state_set)(struct dsa_switch *ds, int port,
102162306a36Sopenharmony_ci				      const struct switchdev_mst_state *state);
102262306a36Sopenharmony_ci	void	(*port_fast_age)(struct dsa_switch *ds, int port);
102362306a36Sopenharmony_ci	int	(*port_vlan_fast_age)(struct dsa_switch *ds, int port, u16 vid);
102462306a36Sopenharmony_ci	int	(*port_pre_bridge_flags)(struct dsa_switch *ds, int port,
102562306a36Sopenharmony_ci					 struct switchdev_brport_flags flags,
102662306a36Sopenharmony_ci					 struct netlink_ext_ack *extack);
102762306a36Sopenharmony_ci	int	(*port_bridge_flags)(struct dsa_switch *ds, int port,
102862306a36Sopenharmony_ci				     struct switchdev_brport_flags flags,
102962306a36Sopenharmony_ci				     struct netlink_ext_ack *extack);
103062306a36Sopenharmony_ci	void	(*port_set_host_flood)(struct dsa_switch *ds, int port,
103162306a36Sopenharmony_ci				       bool uc, bool mc);
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci	/*
103462306a36Sopenharmony_ci	 * VLAN support
103562306a36Sopenharmony_ci	 */
103662306a36Sopenharmony_ci	int	(*port_vlan_filtering)(struct dsa_switch *ds, int port,
103762306a36Sopenharmony_ci				       bool vlan_filtering,
103862306a36Sopenharmony_ci				       struct netlink_ext_ack *extack);
103962306a36Sopenharmony_ci	int	(*port_vlan_add)(struct dsa_switch *ds, int port,
104062306a36Sopenharmony_ci				 const struct switchdev_obj_port_vlan *vlan,
104162306a36Sopenharmony_ci				 struct netlink_ext_ack *extack);
104262306a36Sopenharmony_ci	int	(*port_vlan_del)(struct dsa_switch *ds, int port,
104362306a36Sopenharmony_ci				 const struct switchdev_obj_port_vlan *vlan);
104462306a36Sopenharmony_ci	int	(*vlan_msti_set)(struct dsa_switch *ds, struct dsa_bridge bridge,
104562306a36Sopenharmony_ci				 const struct switchdev_vlan_msti *msti);
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	/*
104862306a36Sopenharmony_ci	 * Forwarding database
104962306a36Sopenharmony_ci	 */
105062306a36Sopenharmony_ci	int	(*port_fdb_add)(struct dsa_switch *ds, int port,
105162306a36Sopenharmony_ci				const unsigned char *addr, u16 vid,
105262306a36Sopenharmony_ci				struct dsa_db db);
105362306a36Sopenharmony_ci	int	(*port_fdb_del)(struct dsa_switch *ds, int port,
105462306a36Sopenharmony_ci				const unsigned char *addr, u16 vid,
105562306a36Sopenharmony_ci				struct dsa_db db);
105662306a36Sopenharmony_ci	int	(*port_fdb_dump)(struct dsa_switch *ds, int port,
105762306a36Sopenharmony_ci				 dsa_fdb_dump_cb_t *cb, void *data);
105862306a36Sopenharmony_ci	int	(*lag_fdb_add)(struct dsa_switch *ds, struct dsa_lag lag,
105962306a36Sopenharmony_ci			       const unsigned char *addr, u16 vid,
106062306a36Sopenharmony_ci			       struct dsa_db db);
106162306a36Sopenharmony_ci	int	(*lag_fdb_del)(struct dsa_switch *ds, struct dsa_lag lag,
106262306a36Sopenharmony_ci			       const unsigned char *addr, u16 vid,
106362306a36Sopenharmony_ci			       struct dsa_db db);
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci	/*
106662306a36Sopenharmony_ci	 * Multicast database
106762306a36Sopenharmony_ci	 */
106862306a36Sopenharmony_ci	int	(*port_mdb_add)(struct dsa_switch *ds, int port,
106962306a36Sopenharmony_ci				const struct switchdev_obj_port_mdb *mdb,
107062306a36Sopenharmony_ci				struct dsa_db db);
107162306a36Sopenharmony_ci	int	(*port_mdb_del)(struct dsa_switch *ds, int port,
107262306a36Sopenharmony_ci				const struct switchdev_obj_port_mdb *mdb,
107362306a36Sopenharmony_ci				struct dsa_db db);
107462306a36Sopenharmony_ci	/*
107562306a36Sopenharmony_ci	 * RXNFC
107662306a36Sopenharmony_ci	 */
107762306a36Sopenharmony_ci	int	(*get_rxnfc)(struct dsa_switch *ds, int port,
107862306a36Sopenharmony_ci			     struct ethtool_rxnfc *nfc, u32 *rule_locs);
107962306a36Sopenharmony_ci	int	(*set_rxnfc)(struct dsa_switch *ds, int port,
108062306a36Sopenharmony_ci			     struct ethtool_rxnfc *nfc);
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ci	/*
108362306a36Sopenharmony_ci	 * TC integration
108462306a36Sopenharmony_ci	 */
108562306a36Sopenharmony_ci	int	(*cls_flower_add)(struct dsa_switch *ds, int port,
108662306a36Sopenharmony_ci				  struct flow_cls_offload *cls, bool ingress);
108762306a36Sopenharmony_ci	int	(*cls_flower_del)(struct dsa_switch *ds, int port,
108862306a36Sopenharmony_ci				  struct flow_cls_offload *cls, bool ingress);
108962306a36Sopenharmony_ci	int	(*cls_flower_stats)(struct dsa_switch *ds, int port,
109062306a36Sopenharmony_ci				    struct flow_cls_offload *cls, bool ingress);
109162306a36Sopenharmony_ci	int	(*port_mirror_add)(struct dsa_switch *ds, int port,
109262306a36Sopenharmony_ci				   struct dsa_mall_mirror_tc_entry *mirror,
109362306a36Sopenharmony_ci				   bool ingress, struct netlink_ext_ack *extack);
109462306a36Sopenharmony_ci	void	(*port_mirror_del)(struct dsa_switch *ds, int port,
109562306a36Sopenharmony_ci				   struct dsa_mall_mirror_tc_entry *mirror);
109662306a36Sopenharmony_ci	int	(*port_policer_add)(struct dsa_switch *ds, int port,
109762306a36Sopenharmony_ci				    struct dsa_mall_policer_tc_entry *policer);
109862306a36Sopenharmony_ci	void	(*port_policer_del)(struct dsa_switch *ds, int port);
109962306a36Sopenharmony_ci	int	(*port_setup_tc)(struct dsa_switch *ds, int port,
110062306a36Sopenharmony_ci				 enum tc_setup_type type, void *type_data);
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	/*
110362306a36Sopenharmony_ci	 * Cross-chip operations
110462306a36Sopenharmony_ci	 */
110562306a36Sopenharmony_ci	int	(*crosschip_bridge_join)(struct dsa_switch *ds, int tree_index,
110662306a36Sopenharmony_ci					 int sw_index, int port,
110762306a36Sopenharmony_ci					 struct dsa_bridge bridge,
110862306a36Sopenharmony_ci					 struct netlink_ext_ack *extack);
110962306a36Sopenharmony_ci	void	(*crosschip_bridge_leave)(struct dsa_switch *ds, int tree_index,
111062306a36Sopenharmony_ci					  int sw_index, int port,
111162306a36Sopenharmony_ci					  struct dsa_bridge bridge);
111262306a36Sopenharmony_ci	int	(*crosschip_lag_change)(struct dsa_switch *ds, int sw_index,
111362306a36Sopenharmony_ci					int port);
111462306a36Sopenharmony_ci	int	(*crosschip_lag_join)(struct dsa_switch *ds, int sw_index,
111562306a36Sopenharmony_ci				      int port, struct dsa_lag lag,
111662306a36Sopenharmony_ci				      struct netdev_lag_upper_info *info,
111762306a36Sopenharmony_ci				      struct netlink_ext_ack *extack);
111862306a36Sopenharmony_ci	int	(*crosschip_lag_leave)(struct dsa_switch *ds, int sw_index,
111962306a36Sopenharmony_ci				       int port, struct dsa_lag lag);
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	/*
112262306a36Sopenharmony_ci	 * PTP functionality
112362306a36Sopenharmony_ci	 */
112462306a36Sopenharmony_ci	int	(*port_hwtstamp_get)(struct dsa_switch *ds, int port,
112562306a36Sopenharmony_ci				     struct ifreq *ifr);
112662306a36Sopenharmony_ci	int	(*port_hwtstamp_set)(struct dsa_switch *ds, int port,
112762306a36Sopenharmony_ci				     struct ifreq *ifr);
112862306a36Sopenharmony_ci	void	(*port_txtstamp)(struct dsa_switch *ds, int port,
112962306a36Sopenharmony_ci				 struct sk_buff *skb);
113062306a36Sopenharmony_ci	bool	(*port_rxtstamp)(struct dsa_switch *ds, int port,
113162306a36Sopenharmony_ci				 struct sk_buff *skb, unsigned int type);
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_ci	/* Devlink parameters, etc */
113462306a36Sopenharmony_ci	int	(*devlink_param_get)(struct dsa_switch *ds, u32 id,
113562306a36Sopenharmony_ci				     struct devlink_param_gset_ctx *ctx);
113662306a36Sopenharmony_ci	int	(*devlink_param_set)(struct dsa_switch *ds, u32 id,
113762306a36Sopenharmony_ci				     struct devlink_param_gset_ctx *ctx);
113862306a36Sopenharmony_ci	int	(*devlink_info_get)(struct dsa_switch *ds,
113962306a36Sopenharmony_ci				    struct devlink_info_req *req,
114062306a36Sopenharmony_ci				    struct netlink_ext_ack *extack);
114162306a36Sopenharmony_ci	int	(*devlink_sb_pool_get)(struct dsa_switch *ds,
114262306a36Sopenharmony_ci				       unsigned int sb_index, u16 pool_index,
114362306a36Sopenharmony_ci				       struct devlink_sb_pool_info *pool_info);
114462306a36Sopenharmony_ci	int	(*devlink_sb_pool_set)(struct dsa_switch *ds, unsigned int sb_index,
114562306a36Sopenharmony_ci				       u16 pool_index, u32 size,
114662306a36Sopenharmony_ci				       enum devlink_sb_threshold_type threshold_type,
114762306a36Sopenharmony_ci				       struct netlink_ext_ack *extack);
114862306a36Sopenharmony_ci	int	(*devlink_sb_port_pool_get)(struct dsa_switch *ds, int port,
114962306a36Sopenharmony_ci					    unsigned int sb_index, u16 pool_index,
115062306a36Sopenharmony_ci					    u32 *p_threshold);
115162306a36Sopenharmony_ci	int	(*devlink_sb_port_pool_set)(struct dsa_switch *ds, int port,
115262306a36Sopenharmony_ci					    unsigned int sb_index, u16 pool_index,
115362306a36Sopenharmony_ci					    u32 threshold,
115462306a36Sopenharmony_ci					    struct netlink_ext_ack *extack);
115562306a36Sopenharmony_ci	int	(*devlink_sb_tc_pool_bind_get)(struct dsa_switch *ds, int port,
115662306a36Sopenharmony_ci					       unsigned int sb_index, u16 tc_index,
115762306a36Sopenharmony_ci					       enum devlink_sb_pool_type pool_type,
115862306a36Sopenharmony_ci					       u16 *p_pool_index, u32 *p_threshold);
115962306a36Sopenharmony_ci	int	(*devlink_sb_tc_pool_bind_set)(struct dsa_switch *ds, int port,
116062306a36Sopenharmony_ci					       unsigned int sb_index, u16 tc_index,
116162306a36Sopenharmony_ci					       enum devlink_sb_pool_type pool_type,
116262306a36Sopenharmony_ci					       u16 pool_index, u32 threshold,
116362306a36Sopenharmony_ci					       struct netlink_ext_ack *extack);
116462306a36Sopenharmony_ci	int	(*devlink_sb_occ_snapshot)(struct dsa_switch *ds,
116562306a36Sopenharmony_ci					   unsigned int sb_index);
116662306a36Sopenharmony_ci	int	(*devlink_sb_occ_max_clear)(struct dsa_switch *ds,
116762306a36Sopenharmony_ci					    unsigned int sb_index);
116862306a36Sopenharmony_ci	int	(*devlink_sb_occ_port_pool_get)(struct dsa_switch *ds, int port,
116962306a36Sopenharmony_ci						unsigned int sb_index, u16 pool_index,
117062306a36Sopenharmony_ci						u32 *p_cur, u32 *p_max);
117162306a36Sopenharmony_ci	int	(*devlink_sb_occ_tc_port_bind_get)(struct dsa_switch *ds, int port,
117262306a36Sopenharmony_ci						   unsigned int sb_index, u16 tc_index,
117362306a36Sopenharmony_ci						   enum devlink_sb_pool_type pool_type,
117462306a36Sopenharmony_ci						   u32 *p_cur, u32 *p_max);
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_ci	/*
117762306a36Sopenharmony_ci	 * MTU change functionality. Switches can also adjust their MRU through
117862306a36Sopenharmony_ci	 * this method. By MTU, one understands the SDU (L2 payload) length.
117962306a36Sopenharmony_ci	 * If the switch needs to account for the DSA tag on the CPU port, this
118062306a36Sopenharmony_ci	 * method needs to do so privately.
118162306a36Sopenharmony_ci	 */
118262306a36Sopenharmony_ci	int	(*port_change_mtu)(struct dsa_switch *ds, int port,
118362306a36Sopenharmony_ci				   int new_mtu);
118462306a36Sopenharmony_ci	int	(*port_max_mtu)(struct dsa_switch *ds, int port);
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci	/*
118762306a36Sopenharmony_ci	 * LAG integration
118862306a36Sopenharmony_ci	 */
118962306a36Sopenharmony_ci	int	(*port_lag_change)(struct dsa_switch *ds, int port);
119062306a36Sopenharmony_ci	int	(*port_lag_join)(struct dsa_switch *ds, int port,
119162306a36Sopenharmony_ci				 struct dsa_lag lag,
119262306a36Sopenharmony_ci				 struct netdev_lag_upper_info *info,
119362306a36Sopenharmony_ci				 struct netlink_ext_ack *extack);
119462306a36Sopenharmony_ci	int	(*port_lag_leave)(struct dsa_switch *ds, int port,
119562306a36Sopenharmony_ci				  struct dsa_lag lag);
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_ci	/*
119862306a36Sopenharmony_ci	 * HSR integration
119962306a36Sopenharmony_ci	 */
120062306a36Sopenharmony_ci	int	(*port_hsr_join)(struct dsa_switch *ds, int port,
120162306a36Sopenharmony_ci				 struct net_device *hsr);
120262306a36Sopenharmony_ci	int	(*port_hsr_leave)(struct dsa_switch *ds, int port,
120362306a36Sopenharmony_ci				  struct net_device *hsr);
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_ci	/*
120662306a36Sopenharmony_ci	 * MRP integration
120762306a36Sopenharmony_ci	 */
120862306a36Sopenharmony_ci	int	(*port_mrp_add)(struct dsa_switch *ds, int port,
120962306a36Sopenharmony_ci				const struct switchdev_obj_mrp *mrp);
121062306a36Sopenharmony_ci	int	(*port_mrp_del)(struct dsa_switch *ds, int port,
121162306a36Sopenharmony_ci				const struct switchdev_obj_mrp *mrp);
121262306a36Sopenharmony_ci	int	(*port_mrp_add_ring_role)(struct dsa_switch *ds, int port,
121362306a36Sopenharmony_ci					  const struct switchdev_obj_ring_role_mrp *mrp);
121462306a36Sopenharmony_ci	int	(*port_mrp_del_ring_role)(struct dsa_switch *ds, int port,
121562306a36Sopenharmony_ci					  const struct switchdev_obj_ring_role_mrp *mrp);
121662306a36Sopenharmony_ci
121762306a36Sopenharmony_ci	/*
121862306a36Sopenharmony_ci	 * tag_8021q operations
121962306a36Sopenharmony_ci	 */
122062306a36Sopenharmony_ci	int	(*tag_8021q_vlan_add)(struct dsa_switch *ds, int port, u16 vid,
122162306a36Sopenharmony_ci				      u16 flags);
122262306a36Sopenharmony_ci	int	(*tag_8021q_vlan_del)(struct dsa_switch *ds, int port, u16 vid);
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci	/*
122562306a36Sopenharmony_ci	 * DSA master tracking operations
122662306a36Sopenharmony_ci	 */
122762306a36Sopenharmony_ci	void	(*master_state_change)(struct dsa_switch *ds,
122862306a36Sopenharmony_ci				       const struct net_device *master,
122962306a36Sopenharmony_ci				       bool operational);
123062306a36Sopenharmony_ci};
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_ci#define DSA_DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes)		\
123362306a36Sopenharmony_ci	DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes,		\
123462306a36Sopenharmony_ci			     dsa_devlink_param_get, dsa_devlink_param_set, NULL)
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_ciint dsa_devlink_param_get(struct devlink *dl, u32 id,
123762306a36Sopenharmony_ci			  struct devlink_param_gset_ctx *ctx);
123862306a36Sopenharmony_ciint dsa_devlink_param_set(struct devlink *dl, u32 id,
123962306a36Sopenharmony_ci			  struct devlink_param_gset_ctx *ctx);
124062306a36Sopenharmony_ciint dsa_devlink_params_register(struct dsa_switch *ds,
124162306a36Sopenharmony_ci				const struct devlink_param *params,
124262306a36Sopenharmony_ci				size_t params_count);
124362306a36Sopenharmony_civoid dsa_devlink_params_unregister(struct dsa_switch *ds,
124462306a36Sopenharmony_ci				   const struct devlink_param *params,
124562306a36Sopenharmony_ci				   size_t params_count);
124662306a36Sopenharmony_ciint dsa_devlink_resource_register(struct dsa_switch *ds,
124762306a36Sopenharmony_ci				  const char *resource_name,
124862306a36Sopenharmony_ci				  u64 resource_size,
124962306a36Sopenharmony_ci				  u64 resource_id,
125062306a36Sopenharmony_ci				  u64 parent_resource_id,
125162306a36Sopenharmony_ci				  const struct devlink_resource_size_params *size_params);
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_civoid dsa_devlink_resources_unregister(struct dsa_switch *ds);
125462306a36Sopenharmony_ci
125562306a36Sopenharmony_civoid dsa_devlink_resource_occ_get_register(struct dsa_switch *ds,
125662306a36Sopenharmony_ci					   u64 resource_id,
125762306a36Sopenharmony_ci					   devlink_resource_occ_get_t *occ_get,
125862306a36Sopenharmony_ci					   void *occ_get_priv);
125962306a36Sopenharmony_civoid dsa_devlink_resource_occ_get_unregister(struct dsa_switch *ds,
126062306a36Sopenharmony_ci					     u64 resource_id);
126162306a36Sopenharmony_cistruct devlink_region *
126262306a36Sopenharmony_cidsa_devlink_region_create(struct dsa_switch *ds,
126362306a36Sopenharmony_ci			  const struct devlink_region_ops *ops,
126462306a36Sopenharmony_ci			  u32 region_max_snapshots, u64 region_size);
126562306a36Sopenharmony_cistruct devlink_region *
126662306a36Sopenharmony_cidsa_devlink_port_region_create(struct dsa_switch *ds,
126762306a36Sopenharmony_ci			       int port,
126862306a36Sopenharmony_ci			       const struct devlink_port_region_ops *ops,
126962306a36Sopenharmony_ci			       u32 region_max_snapshots, u64 region_size);
127062306a36Sopenharmony_civoid dsa_devlink_region_destroy(struct devlink_region *region);
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_cistruct dsa_port *dsa_port_from_netdev(struct net_device *netdev);
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_cistruct dsa_devlink_priv {
127562306a36Sopenharmony_ci	struct dsa_switch *ds;
127662306a36Sopenharmony_ci};
127762306a36Sopenharmony_ci
127862306a36Sopenharmony_cistatic inline struct dsa_switch *dsa_devlink_to_ds(struct devlink *dl)
127962306a36Sopenharmony_ci{
128062306a36Sopenharmony_ci	struct dsa_devlink_priv *dl_priv = devlink_priv(dl);
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_ci	return dl_priv->ds;
128362306a36Sopenharmony_ci}
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_cistatic inline
128662306a36Sopenharmony_cistruct dsa_switch *dsa_devlink_port_to_ds(struct devlink_port *port)
128762306a36Sopenharmony_ci{
128862306a36Sopenharmony_ci	struct devlink *dl = port->devlink;
128962306a36Sopenharmony_ci	struct dsa_devlink_priv *dl_priv = devlink_priv(dl);
129062306a36Sopenharmony_ci
129162306a36Sopenharmony_ci	return dl_priv->ds;
129262306a36Sopenharmony_ci}
129362306a36Sopenharmony_ci
129462306a36Sopenharmony_cistatic inline int dsa_devlink_port_to_port(struct devlink_port *port)
129562306a36Sopenharmony_ci{
129662306a36Sopenharmony_ci	return port->index;
129762306a36Sopenharmony_ci}
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_cistruct dsa_switch_driver {
130062306a36Sopenharmony_ci	struct list_head	list;
130162306a36Sopenharmony_ci	const struct dsa_switch_ops *ops;
130262306a36Sopenharmony_ci};
130362306a36Sopenharmony_ci
130462306a36Sopenharmony_cibool dsa_fdb_present_in_other_db(struct dsa_switch *ds, int port,
130562306a36Sopenharmony_ci				 const unsigned char *addr, u16 vid,
130662306a36Sopenharmony_ci				 struct dsa_db db);
130762306a36Sopenharmony_cibool dsa_mdb_present_in_other_db(struct dsa_switch *ds, int port,
130862306a36Sopenharmony_ci				 const struct switchdev_obj_port_mdb *mdb,
130962306a36Sopenharmony_ci				 struct dsa_db db);
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_ci/* Keep inline for faster access in hot path */
131262306a36Sopenharmony_cistatic inline bool netdev_uses_dsa(const struct net_device *dev)
131362306a36Sopenharmony_ci{
131462306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_NET_DSA)
131562306a36Sopenharmony_ci	return dev->dsa_ptr && dev->dsa_ptr->rcv;
131662306a36Sopenharmony_ci#endif
131762306a36Sopenharmony_ci	return false;
131862306a36Sopenharmony_ci}
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_ci/* All DSA tags that push the EtherType to the right (basically all except tail
132162306a36Sopenharmony_ci * tags, which don't break dissection) can be treated the same from the
132262306a36Sopenharmony_ci * perspective of the flow dissector.
132362306a36Sopenharmony_ci *
132462306a36Sopenharmony_ci * We need to return:
132562306a36Sopenharmony_ci *  - offset: the (B - A) difference between:
132662306a36Sopenharmony_ci *    A. the position of the real EtherType and
132762306a36Sopenharmony_ci *    B. the current skb->data (aka ETH_HLEN bytes into the frame, aka 2 bytes
132862306a36Sopenharmony_ci *       after the normal EtherType was supposed to be)
132962306a36Sopenharmony_ci *    The offset in bytes is exactly equal to the tagger overhead (and half of
133062306a36Sopenharmony_ci *    that, in __be16 shorts).
133162306a36Sopenharmony_ci *
133262306a36Sopenharmony_ci *  - proto: the value of the real EtherType.
133362306a36Sopenharmony_ci */
133462306a36Sopenharmony_cistatic inline void dsa_tag_generic_flow_dissect(const struct sk_buff *skb,
133562306a36Sopenharmony_ci						__be16 *proto, int *offset)
133662306a36Sopenharmony_ci{
133762306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_NET_DSA)
133862306a36Sopenharmony_ci	const struct dsa_device_ops *ops = skb->dev->dsa_ptr->tag_ops;
133962306a36Sopenharmony_ci	int tag_len = ops->needed_headroom;
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci	*offset = tag_len;
134262306a36Sopenharmony_ci	*proto = ((__be16 *)skb->data)[(tag_len / 2) - 1];
134362306a36Sopenharmony_ci#endif
134462306a36Sopenharmony_ci}
134562306a36Sopenharmony_ci
134662306a36Sopenharmony_civoid dsa_unregister_switch(struct dsa_switch *ds);
134762306a36Sopenharmony_ciint dsa_register_switch(struct dsa_switch *ds);
134862306a36Sopenharmony_civoid dsa_switch_shutdown(struct dsa_switch *ds);
134962306a36Sopenharmony_cistruct dsa_switch *dsa_switch_find(int tree_index, int sw_index);
135062306a36Sopenharmony_civoid dsa_flush_workqueue(void);
135162306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
135262306a36Sopenharmony_ciint dsa_switch_suspend(struct dsa_switch *ds);
135362306a36Sopenharmony_ciint dsa_switch_resume(struct dsa_switch *ds);
135462306a36Sopenharmony_ci#else
135562306a36Sopenharmony_cistatic inline int dsa_switch_suspend(struct dsa_switch *ds)
135662306a36Sopenharmony_ci{
135762306a36Sopenharmony_ci	return 0;
135862306a36Sopenharmony_ci}
135962306a36Sopenharmony_cistatic inline int dsa_switch_resume(struct dsa_switch *ds)
136062306a36Sopenharmony_ci{
136162306a36Sopenharmony_ci	return 0;
136262306a36Sopenharmony_ci}
136362306a36Sopenharmony_ci#endif /* CONFIG_PM_SLEEP */
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_NET_DSA)
136662306a36Sopenharmony_cibool dsa_slave_dev_check(const struct net_device *dev);
136762306a36Sopenharmony_ci#else
136862306a36Sopenharmony_cistatic inline bool dsa_slave_dev_check(const struct net_device *dev)
136962306a36Sopenharmony_ci{
137062306a36Sopenharmony_ci	return false;
137162306a36Sopenharmony_ci}
137262306a36Sopenharmony_ci#endif
137362306a36Sopenharmony_ci
137462306a36Sopenharmony_cinetdev_tx_t dsa_enqueue_skb(struct sk_buff *skb, struct net_device *dev);
137562306a36Sopenharmony_civoid dsa_port_phylink_mac_change(struct dsa_switch *ds, int port, bool up);
137662306a36Sopenharmony_ci
137762306a36Sopenharmony_ci#endif
1378