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