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