18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * include/net/dsa.h - Driver for Distributed Switch Architecture switch chips
48c2ecf20Sopenharmony_ci * Copyright (c) 2008-2009 Marvell Semiconductor
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#ifndef __LINUX_NET_DSA_H
88c2ecf20Sopenharmony_ci#define __LINUX_NET_DSA_H
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/if.h>
118c2ecf20Sopenharmony_ci#include <linux/if_ether.h>
128c2ecf20Sopenharmony_ci#include <linux/list.h>
138c2ecf20Sopenharmony_ci#include <linux/notifier.h>
148c2ecf20Sopenharmony_ci#include <linux/timer.h>
158c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
168c2ecf20Sopenharmony_ci#include <linux/of.h>
178c2ecf20Sopenharmony_ci#include <linux/ethtool.h>
188c2ecf20Sopenharmony_ci#include <linux/net_tstamp.h>
198c2ecf20Sopenharmony_ci#include <linux/phy.h>
208c2ecf20Sopenharmony_ci#include <linux/platform_data/dsa.h>
218c2ecf20Sopenharmony_ci#include <linux/phylink.h>
228c2ecf20Sopenharmony_ci#include <net/devlink.h>
238c2ecf20Sopenharmony_ci#include <net/switchdev.h>
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistruct tc_action;
268c2ecf20Sopenharmony_cistruct phy_device;
278c2ecf20Sopenharmony_cistruct fixed_phy_status;
288c2ecf20Sopenharmony_cistruct phylink_link_state;
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#define DSA_TAG_PROTO_NONE_VALUE		0
318c2ecf20Sopenharmony_ci#define DSA_TAG_PROTO_BRCM_VALUE		1
328c2ecf20Sopenharmony_ci#define DSA_TAG_PROTO_BRCM_PREPEND_VALUE	2
338c2ecf20Sopenharmony_ci#define DSA_TAG_PROTO_DSA_VALUE			3
348c2ecf20Sopenharmony_ci#define DSA_TAG_PROTO_EDSA_VALUE		4
358c2ecf20Sopenharmony_ci#define DSA_TAG_PROTO_GSWIP_VALUE		5
368c2ecf20Sopenharmony_ci#define DSA_TAG_PROTO_KSZ9477_VALUE		6
378c2ecf20Sopenharmony_ci#define DSA_TAG_PROTO_KSZ9893_VALUE		7
388c2ecf20Sopenharmony_ci#define DSA_TAG_PROTO_LAN9303_VALUE		8
398c2ecf20Sopenharmony_ci#define DSA_TAG_PROTO_MTK_VALUE			9
408c2ecf20Sopenharmony_ci#define DSA_TAG_PROTO_QCA_VALUE			10
418c2ecf20Sopenharmony_ci#define DSA_TAG_PROTO_TRAILER_VALUE		11
428c2ecf20Sopenharmony_ci#define DSA_TAG_PROTO_8021Q_VALUE		12
438c2ecf20Sopenharmony_ci#define DSA_TAG_PROTO_SJA1105_VALUE		13
448c2ecf20Sopenharmony_ci#define DSA_TAG_PROTO_KSZ8795_VALUE		14
458c2ecf20Sopenharmony_ci#define DSA_TAG_PROTO_OCELOT_VALUE		15
468c2ecf20Sopenharmony_ci#define DSA_TAG_PROTO_AR9331_VALUE		16
478c2ecf20Sopenharmony_ci#define DSA_TAG_PROTO_RTL4_A_VALUE		17
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cienum dsa_tag_protocol {
508c2ecf20Sopenharmony_ci	DSA_TAG_PROTO_NONE		= DSA_TAG_PROTO_NONE_VALUE,
518c2ecf20Sopenharmony_ci	DSA_TAG_PROTO_BRCM		= DSA_TAG_PROTO_BRCM_VALUE,
528c2ecf20Sopenharmony_ci	DSA_TAG_PROTO_BRCM_PREPEND	= DSA_TAG_PROTO_BRCM_PREPEND_VALUE,
538c2ecf20Sopenharmony_ci	DSA_TAG_PROTO_DSA		= DSA_TAG_PROTO_DSA_VALUE,
548c2ecf20Sopenharmony_ci	DSA_TAG_PROTO_EDSA		= DSA_TAG_PROTO_EDSA_VALUE,
558c2ecf20Sopenharmony_ci	DSA_TAG_PROTO_GSWIP		= DSA_TAG_PROTO_GSWIP_VALUE,
568c2ecf20Sopenharmony_ci	DSA_TAG_PROTO_KSZ9477		= DSA_TAG_PROTO_KSZ9477_VALUE,
578c2ecf20Sopenharmony_ci	DSA_TAG_PROTO_KSZ9893		= DSA_TAG_PROTO_KSZ9893_VALUE,
588c2ecf20Sopenharmony_ci	DSA_TAG_PROTO_LAN9303		= DSA_TAG_PROTO_LAN9303_VALUE,
598c2ecf20Sopenharmony_ci	DSA_TAG_PROTO_MTK		= DSA_TAG_PROTO_MTK_VALUE,
608c2ecf20Sopenharmony_ci	DSA_TAG_PROTO_QCA		= DSA_TAG_PROTO_QCA_VALUE,
618c2ecf20Sopenharmony_ci	DSA_TAG_PROTO_TRAILER		= DSA_TAG_PROTO_TRAILER_VALUE,
628c2ecf20Sopenharmony_ci	DSA_TAG_PROTO_8021Q		= DSA_TAG_PROTO_8021Q_VALUE,
638c2ecf20Sopenharmony_ci	DSA_TAG_PROTO_SJA1105		= DSA_TAG_PROTO_SJA1105_VALUE,
648c2ecf20Sopenharmony_ci	DSA_TAG_PROTO_KSZ8795		= DSA_TAG_PROTO_KSZ8795_VALUE,
658c2ecf20Sopenharmony_ci	DSA_TAG_PROTO_OCELOT		= DSA_TAG_PROTO_OCELOT_VALUE,
668c2ecf20Sopenharmony_ci	DSA_TAG_PROTO_AR9331		= DSA_TAG_PROTO_AR9331_VALUE,
678c2ecf20Sopenharmony_ci	DSA_TAG_PROTO_RTL4_A		= DSA_TAG_PROTO_RTL4_A_VALUE,
688c2ecf20Sopenharmony_ci};
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_cistruct packet_type;
718c2ecf20Sopenharmony_cistruct dsa_switch;
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_cistruct dsa_device_ops {
748c2ecf20Sopenharmony_ci	struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
758c2ecf20Sopenharmony_ci	struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
768c2ecf20Sopenharmony_ci			       struct packet_type *pt);
778c2ecf20Sopenharmony_ci	void (*flow_dissect)(const struct sk_buff *skb, __be16 *proto,
788c2ecf20Sopenharmony_ci			     int *offset);
798c2ecf20Sopenharmony_ci	/* Used to determine which traffic should match the DSA filter in
808c2ecf20Sopenharmony_ci	 * eth_type_trans, and which, if any, should bypass it and be processed
818c2ecf20Sopenharmony_ci	 * as regular on the master net device.
828c2ecf20Sopenharmony_ci	 */
838c2ecf20Sopenharmony_ci	bool (*filter)(const struct sk_buff *skb, struct net_device *dev);
848c2ecf20Sopenharmony_ci	unsigned int overhead;
858c2ecf20Sopenharmony_ci	const char *name;
868c2ecf20Sopenharmony_ci	enum dsa_tag_protocol proto;
878c2ecf20Sopenharmony_ci	/* Some tagging protocols either mangle or shift the destination MAC
888c2ecf20Sopenharmony_ci	 * address, in which case the DSA master would drop packets on ingress
898c2ecf20Sopenharmony_ci	 * if what it understands out of the destination MAC address is not in
908c2ecf20Sopenharmony_ci	 * its RX filter.
918c2ecf20Sopenharmony_ci	 */
928c2ecf20Sopenharmony_ci	bool promisc_on_master;
938c2ecf20Sopenharmony_ci	bool tail_tag;
948c2ecf20Sopenharmony_ci};
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci/* This structure defines the control interfaces that are overlayed by the
978c2ecf20Sopenharmony_ci * DSA layer on top of the DSA CPU/management net_device instance. This is
988c2ecf20Sopenharmony_ci * used by the core net_device layer while calling various net_device_ops
998c2ecf20Sopenharmony_ci * function pointers.
1008c2ecf20Sopenharmony_ci */
1018c2ecf20Sopenharmony_cistruct dsa_netdevice_ops {
1028c2ecf20Sopenharmony_ci	int (*ndo_do_ioctl)(struct net_device *dev, struct ifreq *ifr,
1038c2ecf20Sopenharmony_ci			    int cmd);
1048c2ecf20Sopenharmony_ci};
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci#define DSA_TAG_DRIVER_ALIAS "dsa_tag-"
1078c2ecf20Sopenharmony_ci#define MODULE_ALIAS_DSA_TAG_DRIVER(__proto)				\
1088c2ecf20Sopenharmony_ci	MODULE_ALIAS(DSA_TAG_DRIVER_ALIAS __stringify(__proto##_VALUE))
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cistruct dsa_skb_cb {
1118c2ecf20Sopenharmony_ci	struct sk_buff *clone;
1128c2ecf20Sopenharmony_ci};
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_cistruct __dsa_skb_cb {
1158c2ecf20Sopenharmony_ci	struct dsa_skb_cb cb;
1168c2ecf20Sopenharmony_ci	u8 priv[48 - sizeof(struct dsa_skb_cb)];
1178c2ecf20Sopenharmony_ci};
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci#define DSA_SKB_CB(skb) ((struct dsa_skb_cb *)((skb)->cb))
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci#define DSA_SKB_CB_PRIV(skb)			\
1228c2ecf20Sopenharmony_ci	((void *)(skb)->cb + offsetof(struct __dsa_skb_cb, priv))
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_cistruct dsa_switch_tree {
1258c2ecf20Sopenharmony_ci	struct list_head	list;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	/* Notifier chain for switch-wide events */
1288c2ecf20Sopenharmony_ci	struct raw_notifier_head	nh;
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	/* Tree identifier */
1318c2ecf20Sopenharmony_ci	unsigned int index;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	/* Number of switches attached to this tree */
1348c2ecf20Sopenharmony_ci	struct kref refcount;
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	/* Has this tree been applied to the hardware? */
1378c2ecf20Sopenharmony_ci	bool setup;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	/*
1408c2ecf20Sopenharmony_ci	 * Configuration data for the platform device that owns
1418c2ecf20Sopenharmony_ci	 * this dsa switch tree instance.
1428c2ecf20Sopenharmony_ci	 */
1438c2ecf20Sopenharmony_ci	struct dsa_platform_data	*pd;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	/* List of switch ports */
1468c2ecf20Sopenharmony_ci	struct list_head ports;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	/* List of DSA links composing the routing table */
1498c2ecf20Sopenharmony_ci	struct list_head rtable;
1508c2ecf20Sopenharmony_ci};
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci/* TC matchall action types */
1538c2ecf20Sopenharmony_cienum dsa_port_mall_action_type {
1548c2ecf20Sopenharmony_ci	DSA_PORT_MALL_MIRROR,
1558c2ecf20Sopenharmony_ci	DSA_PORT_MALL_POLICER,
1568c2ecf20Sopenharmony_ci};
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci/* TC mirroring entry */
1598c2ecf20Sopenharmony_cistruct dsa_mall_mirror_tc_entry {
1608c2ecf20Sopenharmony_ci	u8 to_local_port;
1618c2ecf20Sopenharmony_ci	bool ingress;
1628c2ecf20Sopenharmony_ci};
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci/* TC port policer entry */
1658c2ecf20Sopenharmony_cistruct dsa_mall_policer_tc_entry {
1668c2ecf20Sopenharmony_ci	u32 burst;
1678c2ecf20Sopenharmony_ci	u64 rate_bytes_per_sec;
1688c2ecf20Sopenharmony_ci};
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci/* TC matchall entry */
1718c2ecf20Sopenharmony_cistruct dsa_mall_tc_entry {
1728c2ecf20Sopenharmony_ci	struct list_head list;
1738c2ecf20Sopenharmony_ci	unsigned long cookie;
1748c2ecf20Sopenharmony_ci	enum dsa_port_mall_action_type type;
1758c2ecf20Sopenharmony_ci	union {
1768c2ecf20Sopenharmony_ci		struct dsa_mall_mirror_tc_entry mirror;
1778c2ecf20Sopenharmony_ci		struct dsa_mall_policer_tc_entry policer;
1788c2ecf20Sopenharmony_ci	};
1798c2ecf20Sopenharmony_ci};
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_cistruct dsa_port {
1838c2ecf20Sopenharmony_ci	/* A CPU port is physically connected to a master device.
1848c2ecf20Sopenharmony_ci	 * A user port exposed to userspace has a slave device.
1858c2ecf20Sopenharmony_ci	 */
1868c2ecf20Sopenharmony_ci	union {
1878c2ecf20Sopenharmony_ci		struct net_device *master;
1888c2ecf20Sopenharmony_ci		struct net_device *slave;
1898c2ecf20Sopenharmony_ci	};
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	/* CPU port tagging operations used by master or slave devices */
1928c2ecf20Sopenharmony_ci	const struct dsa_device_ops *tag_ops;
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	/* Copies for faster access in master receive hot path */
1958c2ecf20Sopenharmony_ci	struct dsa_switch_tree *dst;
1968c2ecf20Sopenharmony_ci	struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
1978c2ecf20Sopenharmony_ci			       struct packet_type *pt);
1988c2ecf20Sopenharmony_ci	bool (*filter)(const struct sk_buff *skb, struct net_device *dev);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	enum {
2018c2ecf20Sopenharmony_ci		DSA_PORT_TYPE_UNUSED = 0,
2028c2ecf20Sopenharmony_ci		DSA_PORT_TYPE_CPU,
2038c2ecf20Sopenharmony_ci		DSA_PORT_TYPE_DSA,
2048c2ecf20Sopenharmony_ci		DSA_PORT_TYPE_USER,
2058c2ecf20Sopenharmony_ci	} type;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	struct dsa_switch	*ds;
2088c2ecf20Sopenharmony_ci	unsigned int		index;
2098c2ecf20Sopenharmony_ci	const char		*name;
2108c2ecf20Sopenharmony_ci	struct dsa_port		*cpu_dp;
2118c2ecf20Sopenharmony_ci	const char		*mac;
2128c2ecf20Sopenharmony_ci	struct device_node	*dn;
2138c2ecf20Sopenharmony_ci	unsigned int		ageing_time;
2148c2ecf20Sopenharmony_ci	bool			vlan_filtering;
2158c2ecf20Sopenharmony_ci	u8			stp_state;
2168c2ecf20Sopenharmony_ci	struct net_device	*bridge_dev;
2178c2ecf20Sopenharmony_ci	struct devlink_port	devlink_port;
2188c2ecf20Sopenharmony_ci	bool			devlink_port_setup;
2198c2ecf20Sopenharmony_ci	struct phylink		*pl;
2208c2ecf20Sopenharmony_ci	struct phylink_config	pl_config;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	struct list_head list;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	/*
2258c2ecf20Sopenharmony_ci	 * Give the switch driver somewhere to hang its per-port private data
2268c2ecf20Sopenharmony_ci	 * structures (accessible from the tagger).
2278c2ecf20Sopenharmony_ci	 */
2288c2ecf20Sopenharmony_ci	void *priv;
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	/*
2318c2ecf20Sopenharmony_ci	 * Original copy of the master netdev ethtool_ops
2328c2ecf20Sopenharmony_ci	 */
2338c2ecf20Sopenharmony_ci	const struct ethtool_ops *orig_ethtool_ops;
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	/*
2368c2ecf20Sopenharmony_ci	 * Original copy of the master netdev net_device_ops
2378c2ecf20Sopenharmony_ci	 */
2388c2ecf20Sopenharmony_ci	const struct dsa_netdevice_ops *netdev_ops;
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	bool setup;
2418c2ecf20Sopenharmony_ci};
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci/* TODO: ideally DSA ports would have a single dp->link_dp member,
2448c2ecf20Sopenharmony_ci * and no dst->rtable nor this struct dsa_link would be needed,
2458c2ecf20Sopenharmony_ci * but this would require some more complex tree walking,
2468c2ecf20Sopenharmony_ci * so keep it stupid at the moment and list them all.
2478c2ecf20Sopenharmony_ci */
2488c2ecf20Sopenharmony_cistruct dsa_link {
2498c2ecf20Sopenharmony_ci	struct dsa_port *dp;
2508c2ecf20Sopenharmony_ci	struct dsa_port *link_dp;
2518c2ecf20Sopenharmony_ci	struct list_head list;
2528c2ecf20Sopenharmony_ci};
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_cistruct dsa_switch {
2558c2ecf20Sopenharmony_ci	bool setup;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	struct device *dev;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	/*
2608c2ecf20Sopenharmony_ci	 * Parent switch tree, and switch index.
2618c2ecf20Sopenharmony_ci	 */
2628c2ecf20Sopenharmony_ci	struct dsa_switch_tree	*dst;
2638c2ecf20Sopenharmony_ci	unsigned int		index;
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	/* Listener for switch fabric events */
2668c2ecf20Sopenharmony_ci	struct notifier_block	nb;
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	/*
2698c2ecf20Sopenharmony_ci	 * Give the switch driver somewhere to hang its private data
2708c2ecf20Sopenharmony_ci	 * structure.
2718c2ecf20Sopenharmony_ci	 */
2728c2ecf20Sopenharmony_ci	void *priv;
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	/*
2758c2ecf20Sopenharmony_ci	 * Configuration data for this switch.
2768c2ecf20Sopenharmony_ci	 */
2778c2ecf20Sopenharmony_ci	struct dsa_chip_data	*cd;
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	/*
2808c2ecf20Sopenharmony_ci	 * The switch operations.
2818c2ecf20Sopenharmony_ci	 */
2828c2ecf20Sopenharmony_ci	const struct dsa_switch_ops	*ops;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	/*
2858c2ecf20Sopenharmony_ci	 * Slave mii_bus and devices for the individual ports.
2868c2ecf20Sopenharmony_ci	 */
2878c2ecf20Sopenharmony_ci	u32			phys_mii_mask;
2888c2ecf20Sopenharmony_ci	struct mii_bus		*slave_mii_bus;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	/* Ageing Time limits in msecs */
2918c2ecf20Sopenharmony_ci	unsigned int ageing_time_min;
2928c2ecf20Sopenharmony_ci	unsigned int ageing_time_max;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	/* devlink used to represent this switch device */
2958c2ecf20Sopenharmony_ci	struct devlink		*devlink;
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	/* Number of switch port queues */
2988c2ecf20Sopenharmony_ci	unsigned int		num_tx_queues;
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	/* Disallow bridge core from requesting different VLAN awareness
3018c2ecf20Sopenharmony_ci	 * settings on ports if not hardware-supported
3028c2ecf20Sopenharmony_ci	 */
3038c2ecf20Sopenharmony_ci	bool			vlan_filtering_is_global;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	/* Pass .port_vlan_add and .port_vlan_del to drivers even for bridges
3068c2ecf20Sopenharmony_ci	 * that have vlan_filtering=0. All drivers should ideally set this (and
3078c2ecf20Sopenharmony_ci	 * then the option would get removed), but it is unknown whether this
3088c2ecf20Sopenharmony_ci	 * would break things or not.
3098c2ecf20Sopenharmony_ci	 */
3108c2ecf20Sopenharmony_ci	bool			configure_vlan_while_not_filtering;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	/* If the switch driver always programs the CPU port as egress tagged
3138c2ecf20Sopenharmony_ci	 * despite the VLAN configuration indicating otherwise, then setting
3148c2ecf20Sopenharmony_ci	 * @untag_bridge_pvid will force the DSA receive path to pop the bridge's
3158c2ecf20Sopenharmony_ci	 * default_pvid VLAN tagged frames to offer a consistent behavior
3168c2ecf20Sopenharmony_ci	 * between a vlan_filtering=0 and vlan_filtering=1 bridge device.
3178c2ecf20Sopenharmony_ci	 */
3188c2ecf20Sopenharmony_ci	bool			untag_bridge_pvid;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	/* In case vlan_filtering_is_global is set, the VLAN awareness state
3218c2ecf20Sopenharmony_ci	 * should be retrieved from here and not from the per-port settings.
3228c2ecf20Sopenharmony_ci	 */
3238c2ecf20Sopenharmony_ci	bool			vlan_filtering;
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	/* MAC PCS does not provide link state change interrupt, and requires
3268c2ecf20Sopenharmony_ci	 * polling. Flag passed on to PHYLINK.
3278c2ecf20Sopenharmony_ci	 */
3288c2ecf20Sopenharmony_ci	bool			pcs_poll;
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	/* For switches that only have the MRU configurable. To ensure the
3318c2ecf20Sopenharmony_ci	 * configured MTU is not exceeded, normalization of MRU on all bridged
3328c2ecf20Sopenharmony_ci	 * interfaces is needed.
3338c2ecf20Sopenharmony_ci	 */
3348c2ecf20Sopenharmony_ci	bool			mtu_enforcement_ingress;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	size_t num_ports;
3378c2ecf20Sopenharmony_ci};
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_cistatic inline struct dsa_port *dsa_to_port(struct dsa_switch *ds, int p)
3408c2ecf20Sopenharmony_ci{
3418c2ecf20Sopenharmony_ci	struct dsa_switch_tree *dst = ds->dst;
3428c2ecf20Sopenharmony_ci	struct dsa_port *dp;
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	list_for_each_entry(dp, &dst->ports, list)
3458c2ecf20Sopenharmony_ci		if (dp->ds == ds && dp->index == p)
3468c2ecf20Sopenharmony_ci			return dp;
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	return NULL;
3498c2ecf20Sopenharmony_ci}
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_cistatic inline bool dsa_is_unused_port(struct dsa_switch *ds, int p)
3528c2ecf20Sopenharmony_ci{
3538c2ecf20Sopenharmony_ci	return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_UNUSED;
3548c2ecf20Sopenharmony_ci}
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_cistatic inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_CPU;
3598c2ecf20Sopenharmony_ci}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_cistatic inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p)
3628c2ecf20Sopenharmony_ci{
3638c2ecf20Sopenharmony_ci	return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_DSA;
3648c2ecf20Sopenharmony_ci}
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_cistatic inline bool dsa_is_user_port(struct dsa_switch *ds, int p)
3678c2ecf20Sopenharmony_ci{
3688c2ecf20Sopenharmony_ci	return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_USER;
3698c2ecf20Sopenharmony_ci}
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_cistatic inline u32 dsa_user_ports(struct dsa_switch *ds)
3728c2ecf20Sopenharmony_ci{
3738c2ecf20Sopenharmony_ci	u32 mask = 0;
3748c2ecf20Sopenharmony_ci	int p;
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	for (p = 0; p < ds->num_ports; p++)
3778c2ecf20Sopenharmony_ci		if (dsa_is_user_port(ds, p))
3788c2ecf20Sopenharmony_ci			mask |= BIT(p);
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	return mask;
3818c2ecf20Sopenharmony_ci}
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci/* Return the local port used to reach an arbitrary switch device */
3848c2ecf20Sopenharmony_cistatic inline unsigned int dsa_routing_port(struct dsa_switch *ds, int device)
3858c2ecf20Sopenharmony_ci{
3868c2ecf20Sopenharmony_ci	struct dsa_switch_tree *dst = ds->dst;
3878c2ecf20Sopenharmony_ci	struct dsa_link *dl;
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	list_for_each_entry(dl, &dst->rtable, list)
3908c2ecf20Sopenharmony_ci		if (dl->dp->ds == ds && dl->link_dp->ds->index == device)
3918c2ecf20Sopenharmony_ci			return dl->dp->index;
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	return ds->num_ports;
3948c2ecf20Sopenharmony_ci}
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci/* Return the local port used to reach an arbitrary switch port */
3978c2ecf20Sopenharmony_cistatic inline unsigned int dsa_towards_port(struct dsa_switch *ds, int device,
3988c2ecf20Sopenharmony_ci					    int port)
3998c2ecf20Sopenharmony_ci{
4008c2ecf20Sopenharmony_ci	if (device == ds->index)
4018c2ecf20Sopenharmony_ci		return port;
4028c2ecf20Sopenharmony_ci	else
4038c2ecf20Sopenharmony_ci		return dsa_routing_port(ds, device);
4048c2ecf20Sopenharmony_ci}
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci/* Return the local port used to reach the dedicated CPU port */
4078c2ecf20Sopenharmony_cistatic inline unsigned int dsa_upstream_port(struct dsa_switch *ds, int port)
4088c2ecf20Sopenharmony_ci{
4098c2ecf20Sopenharmony_ci	const struct dsa_port *dp = dsa_to_port(ds, port);
4108c2ecf20Sopenharmony_ci	const struct dsa_port *cpu_dp = dp->cpu_dp;
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	if (!cpu_dp)
4138c2ecf20Sopenharmony_ci		return port;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	return dsa_towards_port(ds, cpu_dp->ds->index, cpu_dp->index);
4168c2ecf20Sopenharmony_ci}
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_cistatic inline bool dsa_port_is_vlan_filtering(const struct dsa_port *dp)
4198c2ecf20Sopenharmony_ci{
4208c2ecf20Sopenharmony_ci	const struct dsa_switch *ds = dp->ds;
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	if (ds->vlan_filtering_is_global)
4238c2ecf20Sopenharmony_ci		return ds->vlan_filtering;
4248c2ecf20Sopenharmony_ci	else
4258c2ecf20Sopenharmony_ci		return dp->vlan_filtering;
4268c2ecf20Sopenharmony_ci}
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_citypedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid,
4298c2ecf20Sopenharmony_ci			      bool is_static, void *data);
4308c2ecf20Sopenharmony_cistruct dsa_switch_ops {
4318c2ecf20Sopenharmony_ci	enum dsa_tag_protocol (*get_tag_protocol)(struct dsa_switch *ds,
4328c2ecf20Sopenharmony_ci						  int port,
4338c2ecf20Sopenharmony_ci						  enum dsa_tag_protocol mprot);
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	int	(*setup)(struct dsa_switch *ds);
4368c2ecf20Sopenharmony_ci	void	(*teardown)(struct dsa_switch *ds);
4378c2ecf20Sopenharmony_ci	u32	(*get_phy_flags)(struct dsa_switch *ds, int port);
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	/*
4408c2ecf20Sopenharmony_ci	 * Access to the switch's PHY registers.
4418c2ecf20Sopenharmony_ci	 */
4428c2ecf20Sopenharmony_ci	int	(*phy_read)(struct dsa_switch *ds, int port, int regnum);
4438c2ecf20Sopenharmony_ci	int	(*phy_write)(struct dsa_switch *ds, int port,
4448c2ecf20Sopenharmony_ci			     int regnum, u16 val);
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	/*
4478c2ecf20Sopenharmony_ci	 * Link state adjustment (called from libphy)
4488c2ecf20Sopenharmony_ci	 */
4498c2ecf20Sopenharmony_ci	void	(*adjust_link)(struct dsa_switch *ds, int port,
4508c2ecf20Sopenharmony_ci				struct phy_device *phydev);
4518c2ecf20Sopenharmony_ci	void	(*fixed_link_update)(struct dsa_switch *ds, int port,
4528c2ecf20Sopenharmony_ci				struct fixed_phy_status *st);
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	/*
4558c2ecf20Sopenharmony_ci	 * PHYLINK integration
4568c2ecf20Sopenharmony_ci	 */
4578c2ecf20Sopenharmony_ci	void	(*phylink_validate)(struct dsa_switch *ds, int port,
4588c2ecf20Sopenharmony_ci				    unsigned long *supported,
4598c2ecf20Sopenharmony_ci				    struct phylink_link_state *state);
4608c2ecf20Sopenharmony_ci	int	(*phylink_mac_link_state)(struct dsa_switch *ds, int port,
4618c2ecf20Sopenharmony_ci					  struct phylink_link_state *state);
4628c2ecf20Sopenharmony_ci	void	(*phylink_mac_config)(struct dsa_switch *ds, int port,
4638c2ecf20Sopenharmony_ci				      unsigned int mode,
4648c2ecf20Sopenharmony_ci				      const struct phylink_link_state *state);
4658c2ecf20Sopenharmony_ci	void	(*phylink_mac_an_restart)(struct dsa_switch *ds, int port);
4668c2ecf20Sopenharmony_ci	void	(*phylink_mac_link_down)(struct dsa_switch *ds, int port,
4678c2ecf20Sopenharmony_ci					 unsigned int mode,
4688c2ecf20Sopenharmony_ci					 phy_interface_t interface);
4698c2ecf20Sopenharmony_ci	void	(*phylink_mac_link_up)(struct dsa_switch *ds, int port,
4708c2ecf20Sopenharmony_ci				       unsigned int mode,
4718c2ecf20Sopenharmony_ci				       phy_interface_t interface,
4728c2ecf20Sopenharmony_ci				       struct phy_device *phydev,
4738c2ecf20Sopenharmony_ci				       int speed, int duplex,
4748c2ecf20Sopenharmony_ci				       bool tx_pause, bool rx_pause);
4758c2ecf20Sopenharmony_ci	void	(*phylink_fixed_state)(struct dsa_switch *ds, int port,
4768c2ecf20Sopenharmony_ci				       struct phylink_link_state *state);
4778c2ecf20Sopenharmony_ci	/*
4788c2ecf20Sopenharmony_ci	 * ethtool hardware statistics.
4798c2ecf20Sopenharmony_ci	 */
4808c2ecf20Sopenharmony_ci	void	(*get_strings)(struct dsa_switch *ds, int port,
4818c2ecf20Sopenharmony_ci			       u32 stringset, uint8_t *data);
4828c2ecf20Sopenharmony_ci	void	(*get_ethtool_stats)(struct dsa_switch *ds,
4838c2ecf20Sopenharmony_ci				     int port, uint64_t *data);
4848c2ecf20Sopenharmony_ci	int	(*get_sset_count)(struct dsa_switch *ds, int port, int sset);
4858c2ecf20Sopenharmony_ci	void	(*get_ethtool_phy_stats)(struct dsa_switch *ds,
4868c2ecf20Sopenharmony_ci					 int port, uint64_t *data);
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	/*
4898c2ecf20Sopenharmony_ci	 * ethtool Wake-on-LAN
4908c2ecf20Sopenharmony_ci	 */
4918c2ecf20Sopenharmony_ci	void	(*get_wol)(struct dsa_switch *ds, int port,
4928c2ecf20Sopenharmony_ci			   struct ethtool_wolinfo *w);
4938c2ecf20Sopenharmony_ci	int	(*set_wol)(struct dsa_switch *ds, int port,
4948c2ecf20Sopenharmony_ci			   struct ethtool_wolinfo *w);
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	/*
4978c2ecf20Sopenharmony_ci	 * ethtool timestamp info
4988c2ecf20Sopenharmony_ci	 */
4998c2ecf20Sopenharmony_ci	int	(*get_ts_info)(struct dsa_switch *ds, int port,
5008c2ecf20Sopenharmony_ci			       struct ethtool_ts_info *ts);
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	/*
5038c2ecf20Sopenharmony_ci	 * Suspend and resume
5048c2ecf20Sopenharmony_ci	 */
5058c2ecf20Sopenharmony_ci	int	(*suspend)(struct dsa_switch *ds);
5068c2ecf20Sopenharmony_ci	int	(*resume)(struct dsa_switch *ds);
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	/*
5098c2ecf20Sopenharmony_ci	 * Port enable/disable
5108c2ecf20Sopenharmony_ci	 */
5118c2ecf20Sopenharmony_ci	int	(*port_enable)(struct dsa_switch *ds, int port,
5128c2ecf20Sopenharmony_ci			       struct phy_device *phy);
5138c2ecf20Sopenharmony_ci	void	(*port_disable)(struct dsa_switch *ds, int port);
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	/*
5168c2ecf20Sopenharmony_ci	 * Port's MAC EEE settings
5178c2ecf20Sopenharmony_ci	 */
5188c2ecf20Sopenharmony_ci	int	(*set_mac_eee)(struct dsa_switch *ds, int port,
5198c2ecf20Sopenharmony_ci			       struct ethtool_eee *e);
5208c2ecf20Sopenharmony_ci	int	(*get_mac_eee)(struct dsa_switch *ds, int port,
5218c2ecf20Sopenharmony_ci			       struct ethtool_eee *e);
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci	/* EEPROM access */
5248c2ecf20Sopenharmony_ci	int	(*get_eeprom_len)(struct dsa_switch *ds);
5258c2ecf20Sopenharmony_ci	int	(*get_eeprom)(struct dsa_switch *ds,
5268c2ecf20Sopenharmony_ci			      struct ethtool_eeprom *eeprom, u8 *data);
5278c2ecf20Sopenharmony_ci	int	(*set_eeprom)(struct dsa_switch *ds,
5288c2ecf20Sopenharmony_ci			      struct ethtool_eeprom *eeprom, u8 *data);
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	/*
5318c2ecf20Sopenharmony_ci	 * Register access.
5328c2ecf20Sopenharmony_ci	 */
5338c2ecf20Sopenharmony_ci	int	(*get_regs_len)(struct dsa_switch *ds, int port);
5348c2ecf20Sopenharmony_ci	void	(*get_regs)(struct dsa_switch *ds, int port,
5358c2ecf20Sopenharmony_ci			    struct ethtool_regs *regs, void *p);
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	/*
5388c2ecf20Sopenharmony_ci	 * Bridge integration
5398c2ecf20Sopenharmony_ci	 */
5408c2ecf20Sopenharmony_ci	int	(*set_ageing_time)(struct dsa_switch *ds, unsigned int msecs);
5418c2ecf20Sopenharmony_ci	int	(*port_bridge_join)(struct dsa_switch *ds, int port,
5428c2ecf20Sopenharmony_ci				    struct net_device *bridge);
5438c2ecf20Sopenharmony_ci	void	(*port_bridge_leave)(struct dsa_switch *ds, int port,
5448c2ecf20Sopenharmony_ci				     struct net_device *bridge);
5458c2ecf20Sopenharmony_ci	void	(*port_stp_state_set)(struct dsa_switch *ds, int port,
5468c2ecf20Sopenharmony_ci				      u8 state);
5478c2ecf20Sopenharmony_ci	void	(*port_fast_age)(struct dsa_switch *ds, int port);
5488c2ecf20Sopenharmony_ci	int	(*port_egress_floods)(struct dsa_switch *ds, int port,
5498c2ecf20Sopenharmony_ci				      bool unicast, bool multicast);
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	/*
5528c2ecf20Sopenharmony_ci	 * VLAN support
5538c2ecf20Sopenharmony_ci	 */
5548c2ecf20Sopenharmony_ci	int	(*port_vlan_filtering)(struct dsa_switch *ds, int port,
5558c2ecf20Sopenharmony_ci				       bool vlan_filtering,
5568c2ecf20Sopenharmony_ci				       struct switchdev_trans *trans);
5578c2ecf20Sopenharmony_ci	int (*port_vlan_prepare)(struct dsa_switch *ds, int port,
5588c2ecf20Sopenharmony_ci				 const struct switchdev_obj_port_vlan *vlan);
5598c2ecf20Sopenharmony_ci	void (*port_vlan_add)(struct dsa_switch *ds, int port,
5608c2ecf20Sopenharmony_ci			      const struct switchdev_obj_port_vlan *vlan);
5618c2ecf20Sopenharmony_ci	int	(*port_vlan_del)(struct dsa_switch *ds, int port,
5628c2ecf20Sopenharmony_ci				 const struct switchdev_obj_port_vlan *vlan);
5638c2ecf20Sopenharmony_ci	/*
5648c2ecf20Sopenharmony_ci	 * Forwarding database
5658c2ecf20Sopenharmony_ci	 */
5668c2ecf20Sopenharmony_ci	int	(*port_fdb_add)(struct dsa_switch *ds, int port,
5678c2ecf20Sopenharmony_ci				const unsigned char *addr, u16 vid);
5688c2ecf20Sopenharmony_ci	int	(*port_fdb_del)(struct dsa_switch *ds, int port,
5698c2ecf20Sopenharmony_ci				const unsigned char *addr, u16 vid);
5708c2ecf20Sopenharmony_ci	int	(*port_fdb_dump)(struct dsa_switch *ds, int port,
5718c2ecf20Sopenharmony_ci				 dsa_fdb_dump_cb_t *cb, void *data);
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	/*
5748c2ecf20Sopenharmony_ci	 * Multicast database
5758c2ecf20Sopenharmony_ci	 */
5768c2ecf20Sopenharmony_ci	int (*port_mdb_prepare)(struct dsa_switch *ds, int port,
5778c2ecf20Sopenharmony_ci				const struct switchdev_obj_port_mdb *mdb);
5788c2ecf20Sopenharmony_ci	void (*port_mdb_add)(struct dsa_switch *ds, int port,
5798c2ecf20Sopenharmony_ci			     const struct switchdev_obj_port_mdb *mdb);
5808c2ecf20Sopenharmony_ci	int	(*port_mdb_del)(struct dsa_switch *ds, int port,
5818c2ecf20Sopenharmony_ci				const struct switchdev_obj_port_mdb *mdb);
5828c2ecf20Sopenharmony_ci	/*
5838c2ecf20Sopenharmony_ci	 * RXNFC
5848c2ecf20Sopenharmony_ci	 */
5858c2ecf20Sopenharmony_ci	int	(*get_rxnfc)(struct dsa_switch *ds, int port,
5868c2ecf20Sopenharmony_ci			     struct ethtool_rxnfc *nfc, u32 *rule_locs);
5878c2ecf20Sopenharmony_ci	int	(*set_rxnfc)(struct dsa_switch *ds, int port,
5888c2ecf20Sopenharmony_ci			     struct ethtool_rxnfc *nfc);
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	/*
5918c2ecf20Sopenharmony_ci	 * TC integration
5928c2ecf20Sopenharmony_ci	 */
5938c2ecf20Sopenharmony_ci	int	(*cls_flower_add)(struct dsa_switch *ds, int port,
5948c2ecf20Sopenharmony_ci				  struct flow_cls_offload *cls, bool ingress);
5958c2ecf20Sopenharmony_ci	int	(*cls_flower_del)(struct dsa_switch *ds, int port,
5968c2ecf20Sopenharmony_ci				  struct flow_cls_offload *cls, bool ingress);
5978c2ecf20Sopenharmony_ci	int	(*cls_flower_stats)(struct dsa_switch *ds, int port,
5988c2ecf20Sopenharmony_ci				    struct flow_cls_offload *cls, bool ingress);
5998c2ecf20Sopenharmony_ci	int	(*port_mirror_add)(struct dsa_switch *ds, int port,
6008c2ecf20Sopenharmony_ci				   struct dsa_mall_mirror_tc_entry *mirror,
6018c2ecf20Sopenharmony_ci				   bool ingress);
6028c2ecf20Sopenharmony_ci	void	(*port_mirror_del)(struct dsa_switch *ds, int port,
6038c2ecf20Sopenharmony_ci				   struct dsa_mall_mirror_tc_entry *mirror);
6048c2ecf20Sopenharmony_ci	int	(*port_policer_add)(struct dsa_switch *ds, int port,
6058c2ecf20Sopenharmony_ci				    struct dsa_mall_policer_tc_entry *policer);
6068c2ecf20Sopenharmony_ci	void	(*port_policer_del)(struct dsa_switch *ds, int port);
6078c2ecf20Sopenharmony_ci	int	(*port_setup_tc)(struct dsa_switch *ds, int port,
6088c2ecf20Sopenharmony_ci				 enum tc_setup_type type, void *type_data);
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	/*
6118c2ecf20Sopenharmony_ci	 * Cross-chip operations
6128c2ecf20Sopenharmony_ci	 */
6138c2ecf20Sopenharmony_ci	int	(*crosschip_bridge_join)(struct dsa_switch *ds, int tree_index,
6148c2ecf20Sopenharmony_ci					 int sw_index, int port,
6158c2ecf20Sopenharmony_ci					 struct net_device *br);
6168c2ecf20Sopenharmony_ci	void	(*crosschip_bridge_leave)(struct dsa_switch *ds, int tree_index,
6178c2ecf20Sopenharmony_ci					  int sw_index, int port,
6188c2ecf20Sopenharmony_ci					  struct net_device *br);
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	/*
6218c2ecf20Sopenharmony_ci	 * PTP functionality
6228c2ecf20Sopenharmony_ci	 */
6238c2ecf20Sopenharmony_ci	int	(*port_hwtstamp_get)(struct dsa_switch *ds, int port,
6248c2ecf20Sopenharmony_ci				     struct ifreq *ifr);
6258c2ecf20Sopenharmony_ci	int	(*port_hwtstamp_set)(struct dsa_switch *ds, int port,
6268c2ecf20Sopenharmony_ci				     struct ifreq *ifr);
6278c2ecf20Sopenharmony_ci	bool	(*port_txtstamp)(struct dsa_switch *ds, int port,
6288c2ecf20Sopenharmony_ci				 struct sk_buff *clone, unsigned int type);
6298c2ecf20Sopenharmony_ci	bool	(*port_rxtstamp)(struct dsa_switch *ds, int port,
6308c2ecf20Sopenharmony_ci				 struct sk_buff *skb, unsigned int type);
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	/* Devlink parameters, etc */
6338c2ecf20Sopenharmony_ci	int	(*devlink_param_get)(struct dsa_switch *ds, u32 id,
6348c2ecf20Sopenharmony_ci				     struct devlink_param_gset_ctx *ctx);
6358c2ecf20Sopenharmony_ci	int	(*devlink_param_set)(struct dsa_switch *ds, u32 id,
6368c2ecf20Sopenharmony_ci				     struct devlink_param_gset_ctx *ctx);
6378c2ecf20Sopenharmony_ci	int	(*devlink_info_get)(struct dsa_switch *ds,
6388c2ecf20Sopenharmony_ci				    struct devlink_info_req *req,
6398c2ecf20Sopenharmony_ci				    struct netlink_ext_ack *extack);
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	/*
6428c2ecf20Sopenharmony_ci	 * MTU change functionality. Switches can also adjust their MRU through
6438c2ecf20Sopenharmony_ci	 * this method. By MTU, one understands the SDU (L2 payload) length.
6448c2ecf20Sopenharmony_ci	 * If the switch needs to account for the DSA tag on the CPU port, this
6458c2ecf20Sopenharmony_ci	 * method needs to do so privately.
6468c2ecf20Sopenharmony_ci	 */
6478c2ecf20Sopenharmony_ci	int	(*port_change_mtu)(struct dsa_switch *ds, int port,
6488c2ecf20Sopenharmony_ci				   int new_mtu);
6498c2ecf20Sopenharmony_ci	int	(*port_max_mtu)(struct dsa_switch *ds, int port);
6508c2ecf20Sopenharmony_ci};
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci#define DSA_DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes)		\
6538c2ecf20Sopenharmony_ci	DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes,		\
6548c2ecf20Sopenharmony_ci			     dsa_devlink_param_get, dsa_devlink_param_set, NULL)
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ciint dsa_devlink_param_get(struct devlink *dl, u32 id,
6578c2ecf20Sopenharmony_ci			  struct devlink_param_gset_ctx *ctx);
6588c2ecf20Sopenharmony_ciint dsa_devlink_param_set(struct devlink *dl, u32 id,
6598c2ecf20Sopenharmony_ci			  struct devlink_param_gset_ctx *ctx);
6608c2ecf20Sopenharmony_ciint dsa_devlink_params_register(struct dsa_switch *ds,
6618c2ecf20Sopenharmony_ci				const struct devlink_param *params,
6628c2ecf20Sopenharmony_ci				size_t params_count);
6638c2ecf20Sopenharmony_civoid dsa_devlink_params_unregister(struct dsa_switch *ds,
6648c2ecf20Sopenharmony_ci				   const struct devlink_param *params,
6658c2ecf20Sopenharmony_ci				   size_t params_count);
6668c2ecf20Sopenharmony_ciint dsa_devlink_resource_register(struct dsa_switch *ds,
6678c2ecf20Sopenharmony_ci				  const char *resource_name,
6688c2ecf20Sopenharmony_ci				  u64 resource_size,
6698c2ecf20Sopenharmony_ci				  u64 resource_id,
6708c2ecf20Sopenharmony_ci				  u64 parent_resource_id,
6718c2ecf20Sopenharmony_ci				  const struct devlink_resource_size_params *size_params);
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_civoid dsa_devlink_resources_unregister(struct dsa_switch *ds);
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_civoid dsa_devlink_resource_occ_get_register(struct dsa_switch *ds,
6768c2ecf20Sopenharmony_ci					   u64 resource_id,
6778c2ecf20Sopenharmony_ci					   devlink_resource_occ_get_t *occ_get,
6788c2ecf20Sopenharmony_ci					   void *occ_get_priv);
6798c2ecf20Sopenharmony_civoid dsa_devlink_resource_occ_get_unregister(struct dsa_switch *ds,
6808c2ecf20Sopenharmony_ci					     u64 resource_id);
6818c2ecf20Sopenharmony_cistruct devlink_region *
6828c2ecf20Sopenharmony_cidsa_devlink_region_create(struct dsa_switch *ds,
6838c2ecf20Sopenharmony_ci			  const struct devlink_region_ops *ops,
6848c2ecf20Sopenharmony_ci			  u32 region_max_snapshots, u64 region_size);
6858c2ecf20Sopenharmony_cistruct devlink_region *
6868c2ecf20Sopenharmony_cidsa_devlink_port_region_create(struct dsa_switch *ds,
6878c2ecf20Sopenharmony_ci			       int port,
6888c2ecf20Sopenharmony_ci			       const struct devlink_port_region_ops *ops,
6898c2ecf20Sopenharmony_ci			       u32 region_max_snapshots, u64 region_size);
6908c2ecf20Sopenharmony_civoid dsa_devlink_region_destroy(struct devlink_region *region);
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_cistruct dsa_port *dsa_port_from_netdev(struct net_device *netdev);
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_cistruct dsa_devlink_priv {
6958c2ecf20Sopenharmony_ci	struct dsa_switch *ds;
6968c2ecf20Sopenharmony_ci};
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_cistatic inline struct dsa_switch *dsa_devlink_to_ds(struct devlink *dl)
6998c2ecf20Sopenharmony_ci{
7008c2ecf20Sopenharmony_ci	struct dsa_devlink_priv *dl_priv = devlink_priv(dl);
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	return dl_priv->ds;
7038c2ecf20Sopenharmony_ci}
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_cistatic inline
7068c2ecf20Sopenharmony_cistruct dsa_switch *dsa_devlink_port_to_ds(struct devlink_port *port)
7078c2ecf20Sopenharmony_ci{
7088c2ecf20Sopenharmony_ci	struct devlink *dl = port->devlink;
7098c2ecf20Sopenharmony_ci	struct dsa_devlink_priv *dl_priv = devlink_priv(dl);
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	return dl_priv->ds;
7128c2ecf20Sopenharmony_ci}
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_cistatic inline int dsa_devlink_port_to_port(struct devlink_port *port)
7158c2ecf20Sopenharmony_ci{
7168c2ecf20Sopenharmony_ci	return port->index;
7178c2ecf20Sopenharmony_ci}
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_cistruct dsa_switch_driver {
7208c2ecf20Sopenharmony_ci	struct list_head	list;
7218c2ecf20Sopenharmony_ci	const struct dsa_switch_ops *ops;
7228c2ecf20Sopenharmony_ci};
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_cistruct net_device *dsa_dev_to_net_device(struct device *dev);
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci/* Keep inline for faster access in hot path */
7278c2ecf20Sopenharmony_cistatic inline bool netdev_uses_dsa(const struct net_device *dev)
7288c2ecf20Sopenharmony_ci{
7298c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_NET_DSA)
7308c2ecf20Sopenharmony_ci	return dev->dsa_ptr && dev->dsa_ptr->rcv;
7318c2ecf20Sopenharmony_ci#endif
7328c2ecf20Sopenharmony_ci	return false;
7338c2ecf20Sopenharmony_ci}
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_cistatic inline bool dsa_can_decode(const struct sk_buff *skb,
7368c2ecf20Sopenharmony_ci				  struct net_device *dev)
7378c2ecf20Sopenharmony_ci{
7388c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_NET_DSA)
7398c2ecf20Sopenharmony_ci	return !dev->dsa_ptr->filter || dev->dsa_ptr->filter(skb, dev);
7408c2ecf20Sopenharmony_ci#endif
7418c2ecf20Sopenharmony_ci	return false;
7428c2ecf20Sopenharmony_ci}
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci/* All DSA tags that push the EtherType to the right (basically all except tail
7458c2ecf20Sopenharmony_ci * tags, which don't break dissection) can be treated the same from the
7468c2ecf20Sopenharmony_ci * perspective of the flow dissector.
7478c2ecf20Sopenharmony_ci *
7488c2ecf20Sopenharmony_ci * We need to return:
7498c2ecf20Sopenharmony_ci *  - offset: the (B - A) difference between:
7508c2ecf20Sopenharmony_ci *    A. the position of the real EtherType and
7518c2ecf20Sopenharmony_ci *    B. the current skb->data (aka ETH_HLEN bytes into the frame, aka 2 bytes
7528c2ecf20Sopenharmony_ci *       after the normal EtherType was supposed to be)
7538c2ecf20Sopenharmony_ci *    The offset in bytes is exactly equal to the tagger overhead (and half of
7548c2ecf20Sopenharmony_ci *    that, in __be16 shorts).
7558c2ecf20Sopenharmony_ci *
7568c2ecf20Sopenharmony_ci *  - proto: the value of the real EtherType.
7578c2ecf20Sopenharmony_ci */
7588c2ecf20Sopenharmony_cistatic inline void dsa_tag_generic_flow_dissect(const struct sk_buff *skb,
7598c2ecf20Sopenharmony_ci						__be16 *proto, int *offset)
7608c2ecf20Sopenharmony_ci{
7618c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_NET_DSA)
7628c2ecf20Sopenharmony_ci	const struct dsa_device_ops *ops = skb->dev->dsa_ptr->tag_ops;
7638c2ecf20Sopenharmony_ci	int tag_len = ops->overhead;
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci	*offset = tag_len;
7668c2ecf20Sopenharmony_ci	*proto = ((__be16 *)skb->data)[(tag_len / 2) - 1];
7678c2ecf20Sopenharmony_ci#endif
7688c2ecf20Sopenharmony_ci}
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_NET_DSA)
7718c2ecf20Sopenharmony_cistatic inline int __dsa_netdevice_ops_check(struct net_device *dev)
7728c2ecf20Sopenharmony_ci{
7738c2ecf20Sopenharmony_ci	int err = -EOPNOTSUPP;
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci	if (!dev->dsa_ptr)
7768c2ecf20Sopenharmony_ci		return err;
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	if (!dev->dsa_ptr->netdev_ops)
7798c2ecf20Sopenharmony_ci		return err;
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_ci	return 0;
7828c2ecf20Sopenharmony_ci}
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_cistatic inline int dsa_ndo_do_ioctl(struct net_device *dev, struct ifreq *ifr,
7858c2ecf20Sopenharmony_ci				   int cmd)
7868c2ecf20Sopenharmony_ci{
7878c2ecf20Sopenharmony_ci	const struct dsa_netdevice_ops *ops;
7888c2ecf20Sopenharmony_ci	int err;
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	err = __dsa_netdevice_ops_check(dev);
7918c2ecf20Sopenharmony_ci	if (err)
7928c2ecf20Sopenharmony_ci		return err;
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_ci	ops = dev->dsa_ptr->netdev_ops;
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ci	return ops->ndo_do_ioctl(dev, ifr, cmd);
7978c2ecf20Sopenharmony_ci}
7988c2ecf20Sopenharmony_ci#else
7998c2ecf20Sopenharmony_cistatic inline int dsa_ndo_do_ioctl(struct net_device *dev, struct ifreq *ifr,
8008c2ecf20Sopenharmony_ci				   int cmd)
8018c2ecf20Sopenharmony_ci{
8028c2ecf20Sopenharmony_ci	return -EOPNOTSUPP;
8038c2ecf20Sopenharmony_ci}
8048c2ecf20Sopenharmony_ci#endif
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_civoid dsa_unregister_switch(struct dsa_switch *ds);
8078c2ecf20Sopenharmony_ciint dsa_register_switch(struct dsa_switch *ds);
8088c2ecf20Sopenharmony_cistruct dsa_switch *dsa_switch_find(int tree_index, int sw_index);
8098c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
8108c2ecf20Sopenharmony_ciint dsa_switch_suspend(struct dsa_switch *ds);
8118c2ecf20Sopenharmony_ciint dsa_switch_resume(struct dsa_switch *ds);
8128c2ecf20Sopenharmony_ci#else
8138c2ecf20Sopenharmony_cistatic inline int dsa_switch_suspend(struct dsa_switch *ds)
8148c2ecf20Sopenharmony_ci{
8158c2ecf20Sopenharmony_ci	return 0;
8168c2ecf20Sopenharmony_ci}
8178c2ecf20Sopenharmony_cistatic inline int dsa_switch_resume(struct dsa_switch *ds)
8188c2ecf20Sopenharmony_ci{
8198c2ecf20Sopenharmony_ci	return 0;
8208c2ecf20Sopenharmony_ci}
8218c2ecf20Sopenharmony_ci#endif /* CONFIG_PM_SLEEP */
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_cienum dsa_notifier_type {
8248c2ecf20Sopenharmony_ci	DSA_PORT_REGISTER,
8258c2ecf20Sopenharmony_ci	DSA_PORT_UNREGISTER,
8268c2ecf20Sopenharmony_ci};
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_cistruct dsa_notifier_info {
8298c2ecf20Sopenharmony_ci	struct net_device *dev;
8308c2ecf20Sopenharmony_ci};
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_cistruct dsa_notifier_register_info {
8338c2ecf20Sopenharmony_ci	struct dsa_notifier_info info;	/* must be first */
8348c2ecf20Sopenharmony_ci	struct net_device *master;
8358c2ecf20Sopenharmony_ci	unsigned int port_number;
8368c2ecf20Sopenharmony_ci	unsigned int switch_number;
8378c2ecf20Sopenharmony_ci};
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_cistatic inline struct net_device *
8408c2ecf20Sopenharmony_cidsa_notifier_info_to_dev(const struct dsa_notifier_info *info)
8418c2ecf20Sopenharmony_ci{
8428c2ecf20Sopenharmony_ci	return info->dev;
8438c2ecf20Sopenharmony_ci}
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_NET_DSA)
8468c2ecf20Sopenharmony_ciint register_dsa_notifier(struct notifier_block *nb);
8478c2ecf20Sopenharmony_ciint unregister_dsa_notifier(struct notifier_block *nb);
8488c2ecf20Sopenharmony_ciint call_dsa_notifiers(unsigned long val, struct net_device *dev,
8498c2ecf20Sopenharmony_ci		       struct dsa_notifier_info *info);
8508c2ecf20Sopenharmony_ci#else
8518c2ecf20Sopenharmony_cistatic inline int register_dsa_notifier(struct notifier_block *nb)
8528c2ecf20Sopenharmony_ci{
8538c2ecf20Sopenharmony_ci	return 0;
8548c2ecf20Sopenharmony_ci}
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_cistatic inline int unregister_dsa_notifier(struct notifier_block *nb)
8578c2ecf20Sopenharmony_ci{
8588c2ecf20Sopenharmony_ci	return 0;
8598c2ecf20Sopenharmony_ci}
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_cistatic inline int call_dsa_notifiers(unsigned long val, struct net_device *dev,
8628c2ecf20Sopenharmony_ci				     struct dsa_notifier_info *info)
8638c2ecf20Sopenharmony_ci{
8648c2ecf20Sopenharmony_ci	return NOTIFY_DONE;
8658c2ecf20Sopenharmony_ci}
8668c2ecf20Sopenharmony_ci#endif
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci/* Broadcom tag specific helpers to insert and extract queue/port number */
8698c2ecf20Sopenharmony_ci#define BRCM_TAG_SET_PORT_QUEUE(p, q)	((p) << 8 | q)
8708c2ecf20Sopenharmony_ci#define BRCM_TAG_GET_PORT(v)		((v) >> 8)
8718c2ecf20Sopenharmony_ci#define BRCM_TAG_GET_QUEUE(v)		((v) & 0xff)
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ci
8748c2ecf20Sopenharmony_cinetdev_tx_t dsa_enqueue_skb(struct sk_buff *skb, struct net_device *dev);
8758c2ecf20Sopenharmony_ciint dsa_port_get_phy_strings(struct dsa_port *dp, uint8_t *data);
8768c2ecf20Sopenharmony_ciint dsa_port_get_ethtool_phy_stats(struct dsa_port *dp, uint64_t *data);
8778c2ecf20Sopenharmony_ciint dsa_port_get_phy_sset_count(struct dsa_port *dp);
8788c2ecf20Sopenharmony_civoid dsa_port_phylink_mac_change(struct dsa_switch *ds, int port, bool up);
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_cistruct dsa_tag_driver {
8818c2ecf20Sopenharmony_ci	const struct dsa_device_ops *ops;
8828c2ecf20Sopenharmony_ci	struct list_head list;
8838c2ecf20Sopenharmony_ci	struct module *owner;
8848c2ecf20Sopenharmony_ci};
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_civoid dsa_tag_drivers_register(struct dsa_tag_driver *dsa_tag_driver_array[],
8878c2ecf20Sopenharmony_ci			      unsigned int count,
8888c2ecf20Sopenharmony_ci			      struct module *owner);
8898c2ecf20Sopenharmony_civoid dsa_tag_drivers_unregister(struct dsa_tag_driver *dsa_tag_driver_array[],
8908c2ecf20Sopenharmony_ci				unsigned int count);
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci#define dsa_tag_driver_module_drivers(__dsa_tag_drivers_array, __count)	\
8938c2ecf20Sopenharmony_cistatic int __init dsa_tag_driver_module_init(void)			\
8948c2ecf20Sopenharmony_ci{									\
8958c2ecf20Sopenharmony_ci	dsa_tag_drivers_register(__dsa_tag_drivers_array, __count,	\
8968c2ecf20Sopenharmony_ci				 THIS_MODULE);				\
8978c2ecf20Sopenharmony_ci	return 0;							\
8988c2ecf20Sopenharmony_ci}									\
8998c2ecf20Sopenharmony_cimodule_init(dsa_tag_driver_module_init);				\
9008c2ecf20Sopenharmony_ci									\
9018c2ecf20Sopenharmony_cistatic void __exit dsa_tag_driver_module_exit(void)			\
9028c2ecf20Sopenharmony_ci{									\
9038c2ecf20Sopenharmony_ci	dsa_tag_drivers_unregister(__dsa_tag_drivers_array, __count);	\
9048c2ecf20Sopenharmony_ci}									\
9058c2ecf20Sopenharmony_cimodule_exit(dsa_tag_driver_module_exit)
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci/**
9088c2ecf20Sopenharmony_ci * module_dsa_tag_drivers() - Helper macro for registering DSA tag
9098c2ecf20Sopenharmony_ci * drivers
9108c2ecf20Sopenharmony_ci * @__ops_array: Array of tag driver strucutres
9118c2ecf20Sopenharmony_ci *
9128c2ecf20Sopenharmony_ci * Helper macro for DSA tag drivers which do not do anything special
9138c2ecf20Sopenharmony_ci * in module init/exit. Each module may only use this macro once, and
9148c2ecf20Sopenharmony_ci * calling it replaces module_init() and module_exit().
9158c2ecf20Sopenharmony_ci */
9168c2ecf20Sopenharmony_ci#define module_dsa_tag_drivers(__ops_array)				\
9178c2ecf20Sopenharmony_cidsa_tag_driver_module_drivers(__ops_array, ARRAY_SIZE(__ops_array))
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci#define DSA_TAG_DRIVER_NAME(__ops) dsa_tag_driver ## _ ## __ops
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_ci/* Create a static structure we can build a linked list of dsa_tag
9228c2ecf20Sopenharmony_ci * drivers
9238c2ecf20Sopenharmony_ci */
9248c2ecf20Sopenharmony_ci#define DSA_TAG_DRIVER(__ops)						\
9258c2ecf20Sopenharmony_cistatic struct dsa_tag_driver DSA_TAG_DRIVER_NAME(__ops) = {		\
9268c2ecf20Sopenharmony_ci	.ops = &__ops,							\
9278c2ecf20Sopenharmony_ci}
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ci/**
9308c2ecf20Sopenharmony_ci * module_dsa_tag_driver() - Helper macro for registering a single DSA tag
9318c2ecf20Sopenharmony_ci * driver
9328c2ecf20Sopenharmony_ci * @__ops: Single tag driver structures
9338c2ecf20Sopenharmony_ci *
9348c2ecf20Sopenharmony_ci * Helper macro for DSA tag drivers which do not do anything special
9358c2ecf20Sopenharmony_ci * in module init/exit. Each module may only use this macro once, and
9368c2ecf20Sopenharmony_ci * calling it replaces module_init() and module_exit().
9378c2ecf20Sopenharmony_ci */
9388c2ecf20Sopenharmony_ci#define module_dsa_tag_driver(__ops)					\
9398c2ecf20Sopenharmony_ciDSA_TAG_DRIVER(__ops);							\
9408c2ecf20Sopenharmony_ci									\
9418c2ecf20Sopenharmony_cistatic struct dsa_tag_driver *dsa_tag_driver_array[] =	{		\
9428c2ecf20Sopenharmony_ci	&DSA_TAG_DRIVER_NAME(__ops)					\
9438c2ecf20Sopenharmony_ci};									\
9448c2ecf20Sopenharmony_cimodule_dsa_tag_drivers(dsa_tag_driver_array)
9458c2ecf20Sopenharmony_ci#endif
9468c2ecf20Sopenharmony_ci
947