xref: /openbmc/linux/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h (revision adcb7aa335af165bf8481a269347b0c75af254f0)
1f48298d3SIoana Ciornei /* SPDX-License-Identifier: GPL-2.0 */
2f48298d3SIoana Ciornei /*
3f48298d3SIoana Ciornei  * DPAA2 Ethernet Switch declarations
4f48298d3SIoana Ciornei  *
5f48298d3SIoana Ciornei  * Copyright 2014-2016 Freescale Semiconductor Inc.
6f48298d3SIoana Ciornei  * Copyright 2017-2021 NXP
7f48298d3SIoana Ciornei  *
8f48298d3SIoana Ciornei  */
9f48298d3SIoana Ciornei 
10f48298d3SIoana Ciornei #ifndef __ETHSW_H
11f48298d3SIoana Ciornei #define __ETHSW_H
12f48298d3SIoana Ciornei 
13f48298d3SIoana Ciornei #include <linux/netdevice.h>
14f48298d3SIoana Ciornei #include <linux/etherdevice.h>
15f48298d3SIoana Ciornei #include <linux/rtnetlink.h>
16f48298d3SIoana Ciornei #include <linux/if_vlan.h>
17f48298d3SIoana Ciornei #include <uapi/linux/if_bridge.h>
18f48298d3SIoana Ciornei #include <net/switchdev.h>
19f48298d3SIoana Ciornei #include <linux/if_bridge.h>
20f48298d3SIoana Ciornei #include <linux/fsl/mc.h>
214ba28c1aSIoana Ciornei #include <net/pkt_cls.h>
22f48298d3SIoana Ciornei #include <soc/fsl/dpaa2-io.h>
23f48298d3SIoana Ciornei 
24f48298d3SIoana Ciornei #include "dpsw.h"
25f48298d3SIoana Ciornei 
26f48298d3SIoana Ciornei /* Number of IRQs supported */
27f48298d3SIoana Ciornei #define DPSW_IRQ_NUM	2
28f48298d3SIoana Ciornei 
29f48298d3SIoana Ciornei /* Port is member of VLAN */
30f48298d3SIoana Ciornei #define ETHSW_VLAN_MEMBER	1
31f48298d3SIoana Ciornei /* VLAN to be treated as untagged on egress */
32f48298d3SIoana Ciornei #define ETHSW_VLAN_UNTAGGED	2
33f48298d3SIoana Ciornei /* Untagged frames will be assigned to this VLAN */
34f48298d3SIoana Ciornei #define ETHSW_VLAN_PVID		4
35f48298d3SIoana Ciornei /* VLAN configured on the switch */
36f48298d3SIoana Ciornei #define ETHSW_VLAN_GLOBAL	8
37f48298d3SIoana Ciornei 
38f48298d3SIoana Ciornei /* Maximum Frame Length supported by HW (currently 10k) */
39f48298d3SIoana Ciornei #define DPAA2_MFL		(10 * 1024)
40f48298d3SIoana Ciornei #define ETHSW_MAX_FRAME_LENGTH	(DPAA2_MFL - VLAN_ETH_HLEN - ETH_FCS_LEN)
41f48298d3SIoana Ciornei #define ETHSW_L2_MAX_FRM(mtu)	((mtu) + VLAN_ETH_HLEN + ETH_FCS_LEN)
42f48298d3SIoana Ciornei 
43f48298d3SIoana Ciornei #define ETHSW_FEATURE_MAC_ADDR	BIT(0)
44f48298d3SIoana Ciornei 
45f48298d3SIoana Ciornei /* Number of receive queues (one RX and one TX_CONF) */
46f48298d3SIoana Ciornei #define DPAA2_SWITCH_RX_NUM_FQS	2
47f48298d3SIoana Ciornei 
48f48298d3SIoana Ciornei /* Hardware requires alignment for ingress/egress buffer addresses */
49f48298d3SIoana Ciornei #define DPAA2_SWITCH_RX_BUF_RAW_SIZE	PAGE_SIZE
50f48298d3SIoana Ciornei #define DPAA2_SWITCH_RX_BUF_TAILROOM \
51f48298d3SIoana Ciornei 	SKB_DATA_ALIGN(sizeof(struct skb_shared_info))
52f48298d3SIoana Ciornei #define DPAA2_SWITCH_RX_BUF_SIZE \
53f48298d3SIoana Ciornei 	(DPAA2_SWITCH_RX_BUF_RAW_SIZE - DPAA2_SWITCH_RX_BUF_TAILROOM)
54f48298d3SIoana Ciornei 
55f48298d3SIoana Ciornei #define DPAA2_SWITCH_STORE_SIZE 16
56f48298d3SIoana Ciornei 
57f48298d3SIoana Ciornei /* Buffer management */
58f48298d3SIoana Ciornei #define BUFS_PER_CMD			7
59f48298d3SIoana Ciornei #define DPAA2_ETHSW_NUM_BUFS		(1024 * BUFS_PER_CMD)
60f48298d3SIoana Ciornei #define DPAA2_ETHSW_REFILL_THRESH	(DPAA2_ETHSW_NUM_BUFS * 5 / 6)
61f48298d3SIoana Ciornei 
62f48298d3SIoana Ciornei /* Number of times to retry DPIO portal operations while waiting
63f48298d3SIoana Ciornei  * for portal to finish executing current command and become
64f48298d3SIoana Ciornei  * available. We want to avoid being stuck in a while loop in case
65f48298d3SIoana Ciornei  * hardware becomes unresponsive, but not give up too easily if
66f48298d3SIoana Ciornei  * the portal really is busy for valid reasons
67f48298d3SIoana Ciornei  */
68f48298d3SIoana Ciornei #define DPAA2_SWITCH_SWP_BUSY_RETRIES		1000
69f48298d3SIoana Ciornei 
70f48298d3SIoana Ciornei /* Hardware annotation buffer size */
71f48298d3SIoana Ciornei #define DPAA2_SWITCH_HWA_SIZE			64
72f48298d3SIoana Ciornei /* Software annotation buffer size */
73f48298d3SIoana Ciornei #define DPAA2_SWITCH_SWA_SIZE			64
74f48298d3SIoana Ciornei 
75f48298d3SIoana Ciornei #define DPAA2_SWITCH_TX_BUF_ALIGN		64
76f48298d3SIoana Ciornei 
77f48298d3SIoana Ciornei #define DPAA2_SWITCH_TX_DATA_OFFSET \
78f48298d3SIoana Ciornei 	(DPAA2_SWITCH_HWA_SIZE + DPAA2_SWITCH_SWA_SIZE)
79f48298d3SIoana Ciornei 
80f48298d3SIoana Ciornei #define DPAA2_SWITCH_NEEDED_HEADROOM \
81f48298d3SIoana Ciornei 	(DPAA2_SWITCH_TX_DATA_OFFSET + DPAA2_SWITCH_TX_BUF_ALIGN)
82f48298d3SIoana Ciornei 
8390f07102SIoana Ciornei #define DPAA2_ETHSW_PORT_MAX_ACL_ENTRIES	16
841110318dSIoana Ciornei #define DPAA2_ETHSW_PORT_DEFAULT_TRAPS		1
851110318dSIoana Ciornei 
861a64ed12SIoana Ciornei #define DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE	256
8790f07102SIoana Ciornei 
88f48298d3SIoana Ciornei extern const struct ethtool_ops dpaa2_switch_port_ethtool_ops;
89f48298d3SIoana Ciornei 
90f48298d3SIoana Ciornei struct ethsw_core;
91f48298d3SIoana Ciornei 
92f48298d3SIoana Ciornei struct dpaa2_switch_fq {
93f48298d3SIoana Ciornei 	struct ethsw_core *ethsw;
94f48298d3SIoana Ciornei 	enum dpsw_queue_type type;
95f48298d3SIoana Ciornei 	struct dpaa2_io_store *store;
96f48298d3SIoana Ciornei 	struct dpaa2_io_notification_ctx nctx;
97f48298d3SIoana Ciornei 	struct napi_struct napi;
98f48298d3SIoana Ciornei 	u32 fqid;
99f48298d3SIoana Ciornei };
100f48298d3SIoana Ciornei 
101f48298d3SIoana Ciornei struct dpaa2_switch_fdb {
102f48298d3SIoana Ciornei 	struct net_device	*bridge_dev;
103f48298d3SIoana Ciornei 	u16			fdb_id;
104f48298d3SIoana Ciornei 	bool			in_use;
105f48298d3SIoana Ciornei };
106f48298d3SIoana Ciornei 
1071110318dSIoana Ciornei struct dpaa2_switch_acl_entry {
1081110318dSIoana Ciornei 	struct list_head	list;
1091110318dSIoana Ciornei 	u16			prio;
1101110318dSIoana Ciornei 	unsigned long		cookie;
1111110318dSIoana Ciornei 
1121110318dSIoana Ciornei 	struct dpsw_acl_entry_cfg cfg;
1131110318dSIoana Ciornei 	struct dpsw_acl_key	key;
1141110318dSIoana Ciornei };
1151110318dSIoana Ciornei 
116*adcb7aa3SIoana Ciornei struct dpaa2_switch_filter_block {
1171110318dSIoana Ciornei 	struct ethsw_core	*ethsw;
1181110318dSIoana Ciornei 	u64			ports;
1191b0f14b6SIoana Ciornei 	bool			in_use;
120*adcb7aa3SIoana Ciornei 
121*adcb7aa3SIoana Ciornei 	struct list_head	acl_entries;
122*adcb7aa3SIoana Ciornei 	u16			acl_id;
123*adcb7aa3SIoana Ciornei 	u8			num_acl_rules;
1241b0f14b6SIoana Ciornei };
1251b0f14b6SIoana Ciornei 
1261110318dSIoana Ciornei static inline bool
127*adcb7aa3SIoana Ciornei dpaa2_switch_acl_tbl_is_full(struct dpaa2_switch_filter_block *filter_block)
1281110318dSIoana Ciornei {
129*adcb7aa3SIoana Ciornei 	if ((filter_block->num_acl_rules + DPAA2_ETHSW_PORT_DEFAULT_TRAPS) >=
1301110318dSIoana Ciornei 	    DPAA2_ETHSW_PORT_MAX_ACL_ENTRIES)
1311110318dSIoana Ciornei 		return true;
1321110318dSIoana Ciornei 	return false;
1331110318dSIoana Ciornei }
1341110318dSIoana Ciornei 
135f48298d3SIoana Ciornei /* Per port private data */
136f48298d3SIoana Ciornei struct ethsw_port_priv {
137f48298d3SIoana Ciornei 	struct net_device	*netdev;
138f48298d3SIoana Ciornei 	u16			idx;
139f48298d3SIoana Ciornei 	struct ethsw_core	*ethsw_data;
140f48298d3SIoana Ciornei 	u8			link_state;
141f48298d3SIoana Ciornei 	u8			stp_state;
142f48298d3SIoana Ciornei 
143f48298d3SIoana Ciornei 	u8			vlans[VLAN_VID_MASK + 1];
144f48298d3SIoana Ciornei 	u16			pvid;
145f48298d3SIoana Ciornei 	u16			tx_qdid;
146f48298d3SIoana Ciornei 
147f48298d3SIoana Ciornei 	struct dpaa2_switch_fdb	*fdb;
148b54eb093SIoana Ciornei 	bool			bcast_flood;
1496253d5e3SIoana Ciornei 	bool			ucast_flood;
15062734c74SIoana Ciornei 	bool			learn_ena;
15190f07102SIoana Ciornei 
152*adcb7aa3SIoana Ciornei 	struct dpaa2_switch_filter_block *filter_block;
153f48298d3SIoana Ciornei };
154f48298d3SIoana Ciornei 
155f48298d3SIoana Ciornei /* Switch data */
156f48298d3SIoana Ciornei struct ethsw_core {
157f48298d3SIoana Ciornei 	struct device			*dev;
158f48298d3SIoana Ciornei 	struct fsl_mc_io		*mc_io;
159f48298d3SIoana Ciornei 	u16				dpsw_handle;
160f48298d3SIoana Ciornei 	struct dpsw_attr		sw_attr;
161f48298d3SIoana Ciornei 	u16				major, minor;
162f48298d3SIoana Ciornei 	unsigned long			features;
163f48298d3SIoana Ciornei 	int				dev_id;
164f48298d3SIoana Ciornei 	struct ethsw_port_priv		**ports;
165f48298d3SIoana Ciornei 	struct iommu_domain		*iommu_domain;
166f48298d3SIoana Ciornei 
167f48298d3SIoana Ciornei 	u8				vlans[VLAN_VID_MASK + 1];
168f48298d3SIoana Ciornei 
169f48298d3SIoana Ciornei 	struct workqueue_struct		*workqueue;
170f48298d3SIoana Ciornei 
171f48298d3SIoana Ciornei 	struct dpaa2_switch_fq		fq[DPAA2_SWITCH_RX_NUM_FQS];
172f48298d3SIoana Ciornei 	struct fsl_mc_device		*dpbp_dev;
173f48298d3SIoana Ciornei 	int				buf_count;
174f48298d3SIoana Ciornei 	u16				bpid;
175f48298d3SIoana Ciornei 	int				napi_users;
176f48298d3SIoana Ciornei 
177f48298d3SIoana Ciornei 	struct dpaa2_switch_fdb		*fdbs;
178*adcb7aa3SIoana Ciornei 	struct dpaa2_switch_filter_block *filter_blocks;
179f48298d3SIoana Ciornei };
180f48298d3SIoana Ciornei 
1811110318dSIoana Ciornei static inline int dpaa2_switch_get_index(struct ethsw_core *ethsw,
1821110318dSIoana Ciornei 					 struct net_device *netdev)
1831110318dSIoana Ciornei {
1841110318dSIoana Ciornei 	int i;
1851110318dSIoana Ciornei 
1861110318dSIoana Ciornei 	for (i = 0; i < ethsw->sw_attr.num_ifs; i++)
1871110318dSIoana Ciornei 		if (ethsw->ports[i]->netdev == netdev)
1881110318dSIoana Ciornei 			return ethsw->ports[i]->idx;
1891110318dSIoana Ciornei 
1901110318dSIoana Ciornei 	return -EINVAL;
1911110318dSIoana Ciornei }
1921110318dSIoana Ciornei 
193f48298d3SIoana Ciornei static inline bool dpaa2_switch_supports_cpu_traffic(struct ethsw_core *ethsw)
194f48298d3SIoana Ciornei {
195f48298d3SIoana Ciornei 	if (ethsw->sw_attr.options & DPSW_OPT_CTRL_IF_DIS) {
196f48298d3SIoana Ciornei 		dev_err(ethsw->dev, "Control Interface is disabled, cannot probe\n");
197f48298d3SIoana Ciornei 		return false;
198f48298d3SIoana Ciornei 	}
199f48298d3SIoana Ciornei 
200f48298d3SIoana Ciornei 	if (ethsw->sw_attr.flooding_cfg != DPSW_FLOODING_PER_FDB) {
201f48298d3SIoana Ciornei 		dev_err(ethsw->dev, "Flooding domain is not per FDB, cannot probe\n");
202f48298d3SIoana Ciornei 		return false;
203f48298d3SIoana Ciornei 	}
204f48298d3SIoana Ciornei 
205f48298d3SIoana Ciornei 	if (ethsw->sw_attr.broadcast_cfg != DPSW_BROADCAST_PER_FDB) {
206f48298d3SIoana Ciornei 		dev_err(ethsw->dev, "Broadcast domain is not per FDB, cannot probe\n");
207f48298d3SIoana Ciornei 		return false;
208f48298d3SIoana Ciornei 	}
209f48298d3SIoana Ciornei 
210f48298d3SIoana Ciornei 	if (ethsw->sw_attr.max_fdbs < ethsw->sw_attr.num_ifs) {
211f48298d3SIoana Ciornei 		dev_err(ethsw->dev, "The number of FDBs is lower than the number of ports, cannot probe\n");
212f48298d3SIoana Ciornei 		return false;
213f48298d3SIoana Ciornei 	}
214f48298d3SIoana Ciornei 
215f48298d3SIoana Ciornei 	return true;
216f48298d3SIoana Ciornei }
217f48298d3SIoana Ciornei 
218f48298d3SIoana Ciornei bool dpaa2_switch_port_dev_check(const struct net_device *netdev);
219f48298d3SIoana Ciornei 
220f48298d3SIoana Ciornei int dpaa2_switch_port_vlans_add(struct net_device *netdev,
221f48298d3SIoana Ciornei 				const struct switchdev_obj_port_vlan *vlan);
222f48298d3SIoana Ciornei 
223f48298d3SIoana Ciornei int dpaa2_switch_port_vlans_del(struct net_device *netdev,
224f48298d3SIoana Ciornei 				const struct switchdev_obj_port_vlan *vlan);
225f48298d3SIoana Ciornei 
226f48298d3SIoana Ciornei typedef int dpaa2_switch_fdb_cb_t(struct ethsw_port_priv *port_priv,
227f48298d3SIoana Ciornei 				  struct fdb_dump_entry *fdb_entry,
228f48298d3SIoana Ciornei 				  void *data);
2291110318dSIoana Ciornei 
2301110318dSIoana Ciornei /* TC offload */
2311110318dSIoana Ciornei 
232*adcb7aa3SIoana Ciornei int dpaa2_switch_cls_flower_replace(struct dpaa2_switch_filter_block *block,
2331110318dSIoana Ciornei 				    struct flow_cls_offload *cls);
2341110318dSIoana Ciornei 
235*adcb7aa3SIoana Ciornei int dpaa2_switch_cls_flower_destroy(struct dpaa2_switch_filter_block *block,
2361110318dSIoana Ciornei 				    struct flow_cls_offload *cls);
2374ba28c1aSIoana Ciornei 
238*adcb7aa3SIoana Ciornei int dpaa2_switch_cls_matchall_replace(struct dpaa2_switch_filter_block *block,
2394ba28c1aSIoana Ciornei 				      struct tc_cls_matchall_offload *cls);
2404ba28c1aSIoana Ciornei 
241*adcb7aa3SIoana Ciornei int dpaa2_switch_cls_matchall_destroy(struct dpaa2_switch_filter_block *block,
2424ba28c1aSIoana Ciornei 				      struct tc_cls_matchall_offload *cls);
24316617954SIoana Ciornei 
244*adcb7aa3SIoana Ciornei int dpaa2_switch_acl_entry_add(struct dpaa2_switch_filter_block *block,
24516617954SIoana Ciornei 			       struct dpaa2_switch_acl_entry *entry);
246f48298d3SIoana Ciornei #endif	/* __ETHSW_H */
247