/* SPDX-License-Identifier: GPL-2.0 */ /* * DPAA2 Ethernet Switch declarations * * Copyright 2014-2016 Freescale Semiconductor Inc. * Copyright 2017-2021 NXP * */ #ifndef __ETHSW_H #define __ETHSW_H #include #include #include #include #include #include #include #include #include #include #include "dpaa2-mac.h" #include "dpsw.h" /* Number of IRQs supported */ #define DPSW_IRQ_NUM 2 /* Port is member of VLAN */ #define ETHSW_VLAN_MEMBER 1 /* VLAN to be treated as untagged on egress */ #define ETHSW_VLAN_UNTAGGED 2 /* Untagged frames will be assigned to this VLAN */ #define ETHSW_VLAN_PVID 4 /* VLAN configured on the switch */ #define ETHSW_VLAN_GLOBAL 8 /* Maximum Frame Length supported by HW (currently 10k) */ #define DPAA2_MFL (10 * 1024) #define ETHSW_MAX_FRAME_LENGTH (DPAA2_MFL - VLAN_ETH_HLEN - ETH_FCS_LEN) #define ETHSW_L2_MAX_FRM(mtu) ((mtu) + VLAN_ETH_HLEN + ETH_FCS_LEN) #define ETHSW_FEATURE_MAC_ADDR BIT(0) /* Number of receive queues (one RX and one TX_CONF) */ #define DPAA2_SWITCH_RX_NUM_FQS 2 /* Hardware requires alignment for ingress/egress buffer addresses */ #define DPAA2_SWITCH_RX_BUF_RAW_SIZE PAGE_SIZE #define DPAA2_SWITCH_RX_BUF_TAILROOM \ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) #define DPAA2_SWITCH_RX_BUF_SIZE \ (DPAA2_SWITCH_RX_BUF_RAW_SIZE - DPAA2_SWITCH_RX_BUF_TAILROOM) #define DPAA2_SWITCH_STORE_SIZE 16 /* Buffer management */ #define BUFS_PER_CMD 7 #define DPAA2_ETHSW_NUM_BUFS (1024 * BUFS_PER_CMD) #define DPAA2_ETHSW_REFILL_THRESH (DPAA2_ETHSW_NUM_BUFS * 5 / 6) /* Number of times to retry DPIO portal operations while waiting * for portal to finish executing current command and become * available. We want to avoid being stuck in a while loop in case * hardware becomes unresponsive, but not give up too easily if * the portal really is busy for valid reasons */ #define DPAA2_SWITCH_SWP_BUSY_RETRIES 1000 /* Hardware annotation buffer size */ #define DPAA2_SWITCH_HWA_SIZE 64 /* Software annotation buffer size */ #define DPAA2_SWITCH_SWA_SIZE 64 #define DPAA2_SWITCH_TX_BUF_ALIGN 64 #define DPAA2_SWITCH_TX_DATA_OFFSET \ (DPAA2_SWITCH_HWA_SIZE + DPAA2_SWITCH_SWA_SIZE) #define DPAA2_SWITCH_NEEDED_HEADROOM \ (DPAA2_SWITCH_TX_DATA_OFFSET + DPAA2_SWITCH_TX_BUF_ALIGN) #define DPAA2_ETHSW_PORT_MAX_ACL_ENTRIES 16 #define DPAA2_ETHSW_PORT_DEFAULT_TRAPS 1 #define DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE 256 extern const struct ethtool_ops dpaa2_switch_port_ethtool_ops; struct ethsw_core; struct dpaa2_switch_fq { struct ethsw_core *ethsw; enum dpsw_queue_type type; struct dpaa2_io_store *store; struct dpaa2_io_notification_ctx nctx; struct napi_struct napi; u32 fqid; }; struct dpaa2_switch_fdb { struct net_device *bridge_dev; u16 fdb_id; bool in_use; }; struct dpaa2_switch_acl_entry { struct list_head list; u16 prio; unsigned long cookie; struct dpsw_acl_entry_cfg cfg; struct dpsw_acl_key key; }; struct dpaa2_switch_mirror_entry { struct list_head list; struct dpsw_reflection_cfg cfg; unsigned long cookie; u16 if_id; }; struct dpaa2_switch_filter_block { struct ethsw_core *ethsw; u64 ports; bool in_use; struct list_head acl_entries; u16 acl_id; u8 num_acl_rules; struct list_head mirror_entries; }; static inline bool dpaa2_switch_acl_tbl_is_full(struct dpaa2_switch_filter_block *filter_block) { if ((filter_block->num_acl_rules + DPAA2_ETHSW_PORT_DEFAULT_TRAPS) >= DPAA2_ETHSW_PORT_MAX_ACL_ENTRIES) return true; return false; } /* Per port private data */ struct ethsw_port_priv { struct net_device *netdev; u16 idx; struct ethsw_core *ethsw_data; u8 link_state; u8 stp_state; u8 vlans[VLAN_VID_MASK + 1]; u16 pvid; u16 tx_qdid; struct dpaa2_switch_fdb *fdb; bool bcast_flood; bool ucast_flood; bool learn_ena; struct dpaa2_switch_filter_block *filter_block; struct dpaa2_mac *mac; }; /* Switch data */ struct ethsw_core { struct device *dev; struct fsl_mc_io *mc_io; u16 dpsw_handle; struct dpsw_attr sw_attr; u16 major, minor; unsigned long features; int dev_id; struct ethsw_port_priv **ports; struct iommu_domain *iommu_domain; u8 vlans[VLAN_VID_MASK + 1]; struct workqueue_struct *workqueue; struct dpaa2_switch_fq fq[DPAA2_SWITCH_RX_NUM_FQS]; struct fsl_mc_device *dpbp_dev; int buf_count; u16 bpid; int napi_users; struct dpaa2_switch_fdb *fdbs; struct dpaa2_switch_filter_block *filter_blocks; u16 mirror_port; }; static inline int dpaa2_switch_get_index(struct ethsw_core *ethsw, struct net_device *netdev) { int i; for (i = 0; i < ethsw->sw_attr.num_ifs; i++) if (ethsw->ports[i]->netdev == netdev) return ethsw->ports[i]->idx; return -EINVAL; } static inline bool dpaa2_switch_supports_cpu_traffic(struct ethsw_core *ethsw) { if (ethsw->sw_attr.options & DPSW_OPT_CTRL_IF_DIS) { dev_err(ethsw->dev, "Control Interface is disabled, cannot probe\n"); return false; } if (ethsw->sw_attr.flooding_cfg != DPSW_FLOODING_PER_FDB) { dev_err(ethsw->dev, "Flooding domain is not per FDB, cannot probe\n"); return false; } if (ethsw->sw_attr.broadcast_cfg != DPSW_BROADCAST_PER_FDB) { dev_err(ethsw->dev, "Broadcast domain is not per FDB, cannot probe\n"); return false; } if (ethsw->sw_attr.max_fdbs < ethsw->sw_attr.num_ifs) { dev_err(ethsw->dev, "The number of FDBs is lower than the number of ports, cannot probe\n"); return false; } return true; } static inline bool dpaa2_switch_port_is_type_phy(struct ethsw_port_priv *port_priv) { if (port_priv->mac && (port_priv->mac->attr.link_type == DPMAC_LINK_TYPE_PHY || port_priv->mac->attr.link_type == DPMAC_LINK_TYPE_BACKPLANE)) return true; return false; } static inline bool dpaa2_switch_port_has_mac(struct ethsw_port_priv *port_priv) { return port_priv->mac ? true : false; } bool dpaa2_switch_port_dev_check(const struct net_device *netdev); int dpaa2_switch_port_vlans_add(struct net_device *netdev, const struct switchdev_obj_port_vlan *vlan); int dpaa2_switch_port_vlans_del(struct net_device *netdev, const struct switchdev_obj_port_vlan *vlan); typedef int dpaa2_switch_fdb_cb_t(struct ethsw_port_priv *port_priv, struct fdb_dump_entry *fdb_entry, void *data); /* TC offload */ int dpaa2_switch_cls_flower_replace(struct dpaa2_switch_filter_block *block, struct flow_cls_offload *cls); int dpaa2_switch_cls_flower_destroy(struct dpaa2_switch_filter_block *block, struct flow_cls_offload *cls); int dpaa2_switch_cls_matchall_replace(struct dpaa2_switch_filter_block *block, struct tc_cls_matchall_offload *cls); int dpaa2_switch_cls_matchall_destroy(struct dpaa2_switch_filter_block *block, struct tc_cls_matchall_offload *cls); int dpaa2_switch_acl_entry_add(struct dpaa2_switch_filter_block *block, struct dpaa2_switch_acl_entry *entry); int dpaa2_switch_block_offload_mirror(struct dpaa2_switch_filter_block *block, struct ethsw_port_priv *port_priv); int dpaa2_switch_block_unoffload_mirror(struct dpaa2_switch_filter_block *block, struct ethsw_port_priv *port_priv); #endif /* __ETHSW_H */