162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * DPAA2 Ethernet Switch declarations
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2014-2016 Freescale Semiconductor Inc.
662306a36Sopenharmony_ci * Copyright 2017-2021 NXP
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#ifndef __ETHSW_H
1162306a36Sopenharmony_ci#define __ETHSW_H
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/netdevice.h>
1462306a36Sopenharmony_ci#include <linux/etherdevice.h>
1562306a36Sopenharmony_ci#include <linux/rtnetlink.h>
1662306a36Sopenharmony_ci#include <linux/if_vlan.h>
1762306a36Sopenharmony_ci#include <uapi/linux/if_bridge.h>
1862306a36Sopenharmony_ci#include <net/switchdev.h>
1962306a36Sopenharmony_ci#include <linux/if_bridge.h>
2062306a36Sopenharmony_ci#include <linux/fsl/mc.h>
2162306a36Sopenharmony_ci#include <net/pkt_cls.h>
2262306a36Sopenharmony_ci#include <soc/fsl/dpaa2-io.h>
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#include "dpaa2-mac.h"
2562306a36Sopenharmony_ci#include "dpsw.h"
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/* Number of IRQs supported */
2862306a36Sopenharmony_ci#define DPSW_IRQ_NUM	2
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/* Port is member of VLAN */
3162306a36Sopenharmony_ci#define ETHSW_VLAN_MEMBER	1
3262306a36Sopenharmony_ci/* VLAN to be treated as untagged on egress */
3362306a36Sopenharmony_ci#define ETHSW_VLAN_UNTAGGED	2
3462306a36Sopenharmony_ci/* Untagged frames will be assigned to this VLAN */
3562306a36Sopenharmony_ci#define ETHSW_VLAN_PVID		4
3662306a36Sopenharmony_ci/* VLAN configured on the switch */
3762306a36Sopenharmony_ci#define ETHSW_VLAN_GLOBAL	8
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci/* Maximum Frame Length supported by HW (currently 10k) */
4062306a36Sopenharmony_ci#define DPAA2_MFL		(10 * 1024)
4162306a36Sopenharmony_ci#define ETHSW_MAX_FRAME_LENGTH	(DPAA2_MFL - VLAN_ETH_HLEN - ETH_FCS_LEN)
4262306a36Sopenharmony_ci#define ETHSW_L2_MAX_FRM(mtu)	((mtu) + VLAN_ETH_HLEN + ETH_FCS_LEN)
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci#define ETHSW_FEATURE_MAC_ADDR	BIT(0)
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci/* Number of receive queues (one RX and one TX_CONF) */
4762306a36Sopenharmony_ci#define DPAA2_SWITCH_RX_NUM_FQS	2
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/* Hardware requires alignment for ingress/egress buffer addresses */
5062306a36Sopenharmony_ci#define DPAA2_SWITCH_RX_BUF_RAW_SIZE	PAGE_SIZE
5162306a36Sopenharmony_ci#define DPAA2_SWITCH_RX_BUF_TAILROOM \
5262306a36Sopenharmony_ci	SKB_DATA_ALIGN(sizeof(struct skb_shared_info))
5362306a36Sopenharmony_ci#define DPAA2_SWITCH_RX_BUF_SIZE \
5462306a36Sopenharmony_ci	(DPAA2_SWITCH_RX_BUF_RAW_SIZE - DPAA2_SWITCH_RX_BUF_TAILROOM)
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci#define DPAA2_SWITCH_STORE_SIZE 16
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci/* Buffer management */
5962306a36Sopenharmony_ci#define BUFS_PER_CMD			7
6062306a36Sopenharmony_ci#define DPAA2_ETHSW_NUM_BUFS		(1024 * BUFS_PER_CMD)
6162306a36Sopenharmony_ci#define DPAA2_ETHSW_REFILL_THRESH	(DPAA2_ETHSW_NUM_BUFS * 5 / 6)
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci/* Number of times to retry DPIO portal operations while waiting
6462306a36Sopenharmony_ci * for portal to finish executing current command and become
6562306a36Sopenharmony_ci * available. We want to avoid being stuck in a while loop in case
6662306a36Sopenharmony_ci * hardware becomes unresponsive, but not give up too easily if
6762306a36Sopenharmony_ci * the portal really is busy for valid reasons
6862306a36Sopenharmony_ci */
6962306a36Sopenharmony_ci#define DPAA2_SWITCH_SWP_BUSY_RETRIES		1000
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci/* Hardware annotation buffer size */
7262306a36Sopenharmony_ci#define DPAA2_SWITCH_HWA_SIZE			64
7362306a36Sopenharmony_ci/* Software annotation buffer size */
7462306a36Sopenharmony_ci#define DPAA2_SWITCH_SWA_SIZE			64
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci#define DPAA2_SWITCH_TX_BUF_ALIGN		64
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci#define DPAA2_SWITCH_TX_DATA_OFFSET \
7962306a36Sopenharmony_ci	(DPAA2_SWITCH_HWA_SIZE + DPAA2_SWITCH_SWA_SIZE)
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci#define DPAA2_SWITCH_NEEDED_HEADROOM \
8262306a36Sopenharmony_ci	(DPAA2_SWITCH_TX_DATA_OFFSET + DPAA2_SWITCH_TX_BUF_ALIGN)
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci#define DPAA2_ETHSW_PORT_MAX_ACL_ENTRIES	16
8562306a36Sopenharmony_ci#define DPAA2_ETHSW_PORT_DEFAULT_TRAPS		1
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci#define DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE	256
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ciextern const struct ethtool_ops dpaa2_switch_port_ethtool_ops;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_cistruct ethsw_core;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistruct dpaa2_switch_fq {
9462306a36Sopenharmony_ci	struct ethsw_core *ethsw;
9562306a36Sopenharmony_ci	enum dpsw_queue_type type;
9662306a36Sopenharmony_ci	struct dpaa2_io_store *store;
9762306a36Sopenharmony_ci	struct dpaa2_io_notification_ctx nctx;
9862306a36Sopenharmony_ci	struct napi_struct napi;
9962306a36Sopenharmony_ci	u32 fqid;
10062306a36Sopenharmony_ci};
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_cistruct dpaa2_switch_fdb {
10362306a36Sopenharmony_ci	struct net_device	*bridge_dev;
10462306a36Sopenharmony_ci	u16			fdb_id;
10562306a36Sopenharmony_ci	bool			in_use;
10662306a36Sopenharmony_ci};
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_cistruct dpaa2_switch_acl_entry {
10962306a36Sopenharmony_ci	struct list_head	list;
11062306a36Sopenharmony_ci	u16			prio;
11162306a36Sopenharmony_ci	unsigned long		cookie;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	struct dpsw_acl_entry_cfg cfg;
11462306a36Sopenharmony_ci	struct dpsw_acl_key	key;
11562306a36Sopenharmony_ci};
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistruct dpaa2_switch_mirror_entry {
11862306a36Sopenharmony_ci	struct list_head	list;
11962306a36Sopenharmony_ci	struct dpsw_reflection_cfg cfg;
12062306a36Sopenharmony_ci	unsigned long		cookie;
12162306a36Sopenharmony_ci	u16 if_id;
12262306a36Sopenharmony_ci};
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cistruct dpaa2_switch_filter_block {
12562306a36Sopenharmony_ci	struct ethsw_core	*ethsw;
12662306a36Sopenharmony_ci	u64			ports;
12762306a36Sopenharmony_ci	bool			in_use;
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	struct list_head	acl_entries;
13062306a36Sopenharmony_ci	u16			acl_id;
13162306a36Sopenharmony_ci	u8			num_acl_rules;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	struct list_head	mirror_entries;
13462306a36Sopenharmony_ci};
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_cistatic inline bool
13762306a36Sopenharmony_cidpaa2_switch_acl_tbl_is_full(struct dpaa2_switch_filter_block *filter_block)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	if ((filter_block->num_acl_rules + DPAA2_ETHSW_PORT_DEFAULT_TRAPS) >=
14062306a36Sopenharmony_ci	    DPAA2_ETHSW_PORT_MAX_ACL_ENTRIES)
14162306a36Sopenharmony_ci		return true;
14262306a36Sopenharmony_ci	return false;
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci/* Per port private data */
14662306a36Sopenharmony_cistruct ethsw_port_priv {
14762306a36Sopenharmony_ci	struct net_device	*netdev;
14862306a36Sopenharmony_ci	u16			idx;
14962306a36Sopenharmony_ci	struct ethsw_core	*ethsw_data;
15062306a36Sopenharmony_ci	u8			link_state;
15162306a36Sopenharmony_ci	u8			stp_state;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	u8			vlans[VLAN_VID_MASK + 1];
15462306a36Sopenharmony_ci	u16			pvid;
15562306a36Sopenharmony_ci	u16			tx_qdid;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	struct dpaa2_switch_fdb	*fdb;
15862306a36Sopenharmony_ci	bool			bcast_flood;
15962306a36Sopenharmony_ci	bool			ucast_flood;
16062306a36Sopenharmony_ci	bool			learn_ena;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	struct dpaa2_switch_filter_block *filter_block;
16362306a36Sopenharmony_ci	struct dpaa2_mac	*mac;
16462306a36Sopenharmony_ci	/* Protects against changes to port_priv->mac */
16562306a36Sopenharmony_ci	struct mutex		mac_lock;
16662306a36Sopenharmony_ci};
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci/* Switch data */
16962306a36Sopenharmony_cistruct ethsw_core {
17062306a36Sopenharmony_ci	struct device			*dev;
17162306a36Sopenharmony_ci	struct fsl_mc_io		*mc_io;
17262306a36Sopenharmony_ci	u16				dpsw_handle;
17362306a36Sopenharmony_ci	struct dpsw_attr		sw_attr;
17462306a36Sopenharmony_ci	u16				major, minor;
17562306a36Sopenharmony_ci	unsigned long			features;
17662306a36Sopenharmony_ci	int				dev_id;
17762306a36Sopenharmony_ci	struct ethsw_port_priv		**ports;
17862306a36Sopenharmony_ci	struct iommu_domain		*iommu_domain;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	u8				vlans[VLAN_VID_MASK + 1];
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	struct workqueue_struct		*workqueue;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	struct dpaa2_switch_fq		fq[DPAA2_SWITCH_RX_NUM_FQS];
18562306a36Sopenharmony_ci	struct fsl_mc_device		*dpbp_dev;
18662306a36Sopenharmony_ci	int				buf_count;
18762306a36Sopenharmony_ci	u16				bpid;
18862306a36Sopenharmony_ci	int				napi_users;
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	struct dpaa2_switch_fdb		*fdbs;
19162306a36Sopenharmony_ci	struct dpaa2_switch_filter_block *filter_blocks;
19262306a36Sopenharmony_ci	u16				mirror_port;
19362306a36Sopenharmony_ci};
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_cistatic inline int dpaa2_switch_get_index(struct ethsw_core *ethsw,
19662306a36Sopenharmony_ci					 struct net_device *netdev)
19762306a36Sopenharmony_ci{
19862306a36Sopenharmony_ci	int i;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	for (i = 0; i < ethsw->sw_attr.num_ifs; i++)
20162306a36Sopenharmony_ci		if (ethsw->ports[i]->netdev == netdev)
20262306a36Sopenharmony_ci			return ethsw->ports[i]->idx;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	return -EINVAL;
20562306a36Sopenharmony_ci}
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_cistatic inline bool dpaa2_switch_supports_cpu_traffic(struct ethsw_core *ethsw)
20862306a36Sopenharmony_ci{
20962306a36Sopenharmony_ci	if (ethsw->sw_attr.options & DPSW_OPT_CTRL_IF_DIS) {
21062306a36Sopenharmony_ci		dev_err(ethsw->dev, "Control Interface is disabled, cannot probe\n");
21162306a36Sopenharmony_ci		return false;
21262306a36Sopenharmony_ci	}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	if (ethsw->sw_attr.flooding_cfg != DPSW_FLOODING_PER_FDB) {
21562306a36Sopenharmony_ci		dev_err(ethsw->dev, "Flooding domain is not per FDB, cannot probe\n");
21662306a36Sopenharmony_ci		return false;
21762306a36Sopenharmony_ci	}
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	if (ethsw->sw_attr.broadcast_cfg != DPSW_BROADCAST_PER_FDB) {
22062306a36Sopenharmony_ci		dev_err(ethsw->dev, "Broadcast domain is not per FDB, cannot probe\n");
22162306a36Sopenharmony_ci		return false;
22262306a36Sopenharmony_ci	}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	if (ethsw->sw_attr.max_fdbs < ethsw->sw_attr.num_ifs) {
22562306a36Sopenharmony_ci		dev_err(ethsw->dev, "The number of FDBs is lower than the number of ports, cannot probe\n");
22662306a36Sopenharmony_ci		return false;
22762306a36Sopenharmony_ci	}
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	return true;
23062306a36Sopenharmony_ci}
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_cistatic inline bool
23362306a36Sopenharmony_cidpaa2_switch_port_is_type_phy(struct ethsw_port_priv *port_priv)
23462306a36Sopenharmony_ci{
23562306a36Sopenharmony_ci	return dpaa2_mac_is_type_phy(port_priv->mac);
23662306a36Sopenharmony_ci}
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cistatic inline bool dpaa2_switch_port_has_mac(struct ethsw_port_priv *port_priv)
23962306a36Sopenharmony_ci{
24062306a36Sopenharmony_ci	return port_priv->mac ? true : false;
24162306a36Sopenharmony_ci}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_cibool dpaa2_switch_port_dev_check(const struct net_device *netdev);
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ciint dpaa2_switch_port_vlans_add(struct net_device *netdev,
24662306a36Sopenharmony_ci				const struct switchdev_obj_port_vlan *vlan);
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ciint dpaa2_switch_port_vlans_del(struct net_device *netdev,
24962306a36Sopenharmony_ci				const struct switchdev_obj_port_vlan *vlan);
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_citypedef int dpaa2_switch_fdb_cb_t(struct ethsw_port_priv *port_priv,
25262306a36Sopenharmony_ci				  struct fdb_dump_entry *fdb_entry,
25362306a36Sopenharmony_ci				  void *data);
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci/* TC offload */
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ciint dpaa2_switch_cls_flower_replace(struct dpaa2_switch_filter_block *block,
25862306a36Sopenharmony_ci				    struct flow_cls_offload *cls);
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ciint dpaa2_switch_cls_flower_destroy(struct dpaa2_switch_filter_block *block,
26162306a36Sopenharmony_ci				    struct flow_cls_offload *cls);
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ciint dpaa2_switch_cls_matchall_replace(struct dpaa2_switch_filter_block *block,
26462306a36Sopenharmony_ci				      struct tc_cls_matchall_offload *cls);
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ciint dpaa2_switch_cls_matchall_destroy(struct dpaa2_switch_filter_block *block,
26762306a36Sopenharmony_ci				      struct tc_cls_matchall_offload *cls);
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ciint dpaa2_switch_acl_entry_add(struct dpaa2_switch_filter_block *block,
27062306a36Sopenharmony_ci			       struct dpaa2_switch_acl_entry *entry);
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ciint dpaa2_switch_block_offload_mirror(struct dpaa2_switch_filter_block *block,
27362306a36Sopenharmony_ci				      struct ethsw_port_priv *port_priv);
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ciint dpaa2_switch_block_unoffload_mirror(struct dpaa2_switch_filter_block *block,
27662306a36Sopenharmony_ci					struct ethsw_port_priv *port_priv);
27762306a36Sopenharmony_ci#endif	/* __ETHSW_H */
278