blob: bdef71f234cbdae4bc4c5c3f05c0c21463159767 [file] [log] [blame]
Michael Straube75f3da82018-12-20 18:14:50 +01001/* SPDX-License-Identifier: GPL-2.0 */
Razvan Stefanescu44baaa42018-03-14 10:55:54 -05002/*
3 * DPAA2 Ethernet Switch declarations
4 *
5 * Copyright 2014-2016 Freescale Semiconductor Inc.
Ioana Ciornei26d419f2021-03-10 14:14:41 +02006 * Copyright 2017-2021 NXP
Razvan Stefanescu44baaa42018-03-14 10:55:54 -05007 *
8 */
9
10#ifndef __ETHSW_H
11#define __ETHSW_H
12
13#include <linux/netdevice.h>
14#include <linux/etherdevice.h>
15#include <linux/rtnetlink.h>
16#include <linux/if_vlan.h>
17#include <uapi/linux/if_bridge.h>
18#include <net/switchdev.h>
19#include <linux/if_bridge.h>
Ioana Ciornei2877e4f2021-03-10 14:14:42 +020020#include <linux/fsl/mc.h>
Ioana Ciornei4ba28c12021-04-13 16:24:47 +030021#include <net/pkt_cls.h>
Ioana Ciornei2877e4f2021-03-10 14:14:42 +020022#include <soc/fsl/dpaa2-io.h>
Razvan Stefanescu44baaa42018-03-14 10:55:54 -050023
24#include "dpsw.h"
25
26/* Number of IRQs supported */
27#define DPSW_IRQ_NUM 2
28
Razvan Stefanescuc5bd72f2019-07-05 17:27:16 +030029/* Port is member of VLAN */
Razvan Stefanescu44baaa42018-03-14 10:55:54 -050030#define ETHSW_VLAN_MEMBER 1
Razvan Stefanescuc5bd72f2019-07-05 17:27:16 +030031/* VLAN to be treated as untagged on egress */
Razvan Stefanescu44baaa42018-03-14 10:55:54 -050032#define ETHSW_VLAN_UNTAGGED 2
Razvan Stefanescuc5bd72f2019-07-05 17:27:16 +030033/* Untagged frames will be assigned to this VLAN */
Razvan Stefanescu44baaa42018-03-14 10:55:54 -050034#define ETHSW_VLAN_PVID 4
Razvan Stefanescuc5bd72f2019-07-05 17:27:16 +030035/* VLAN configured on the switch */
Razvan Stefanescu44baaa42018-03-14 10:55:54 -050036#define ETHSW_VLAN_GLOBAL 8
37
38/* Maximum Frame Length supported by HW (currently 10k) */
39#define DPAA2_MFL (10 * 1024)
40#define ETHSW_MAX_FRAME_LENGTH (DPAA2_MFL - VLAN_ETH_HLEN - ETH_FCS_LEN)
41#define ETHSW_L2_MAX_FRM(mtu) ((mtu) + VLAN_ETH_HLEN + ETH_FCS_LEN)
42
Ioana Ciornei240cb8d2020-07-14 16:34:31 +030043#define ETHSW_FEATURE_MAC_ADDR BIT(0)
44
Ioana Ciornei26d419f2021-03-10 14:14:41 +020045/* Number of receive queues (one RX and one TX_CONF) */
46#define DPAA2_SWITCH_RX_NUM_FQS 2
47
Ioana Ciornei2877e4f2021-03-10 14:14:42 +020048/* Hardware requires alignment for ingress/egress buffer addresses */
49#define DPAA2_SWITCH_RX_BUF_RAW_SIZE PAGE_SIZE
50#define DPAA2_SWITCH_RX_BUF_TAILROOM \
51 SKB_DATA_ALIGN(sizeof(struct skb_shared_info))
52#define DPAA2_SWITCH_RX_BUF_SIZE \
53 (DPAA2_SWITCH_RX_BUF_RAW_SIZE - DPAA2_SWITCH_RX_BUF_TAILROOM)
54
55#define DPAA2_SWITCH_STORE_SIZE 16
56
Ioana Ciornei0b1b7132021-03-10 14:14:44 +020057/* Buffer management */
58#define BUFS_PER_CMD 7
59#define DPAA2_ETHSW_NUM_BUFS (1024 * BUFS_PER_CMD)
60#define DPAA2_ETHSW_REFILL_THRESH (DPAA2_ETHSW_NUM_BUFS * 5 / 6)
61
62/* Number of times to retry DPIO portal operations while waiting
63 * for portal to finish executing current command and become
64 * available. We want to avoid being stuck in a while loop in case
65 * hardware becomes unresponsive, but not give up too easily if
66 * the portal really is busy for valid reasons
67 */
68#define DPAA2_SWITCH_SWP_BUSY_RETRIES 1000
69
Ioana Ciornei7fd94d82021-03-10 14:14:45 +020070/* Hardware annotation buffer size */
71#define DPAA2_SWITCH_HWA_SIZE 64
72/* Software annotation buffer size */
73#define DPAA2_SWITCH_SWA_SIZE 64
74
75#define DPAA2_SWITCH_TX_BUF_ALIGN 64
76
77#define DPAA2_SWITCH_TX_DATA_OFFSET \
78 (DPAA2_SWITCH_HWA_SIZE + DPAA2_SWITCH_SWA_SIZE)
79
80#define DPAA2_SWITCH_NEEDED_HEADROOM \
81 (DPAA2_SWITCH_TX_DATA_OFFSET + DPAA2_SWITCH_TX_BUF_ALIGN)
82
Ioana Ciornei90f07102021-03-30 17:54:16 +030083#define DPAA2_ETHSW_PORT_MAX_ACL_ENTRIES 16
Ioana Ciornei11103182021-04-13 16:24:46 +030084#define DPAA2_ETHSW_PORT_DEFAULT_TRAPS 1
85
Ioana Ciornei1a64ed12021-03-30 17:54:18 +030086#define DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE 256
Ioana Ciornei90f07102021-03-30 17:54:16 +030087
Ioana Ciornei5ad71952020-10-09 18:29:59 +030088extern const struct ethtool_ops dpaa2_switch_port_ethtool_ops;
Razvan Stefanescub2b32122018-03-14 10:55:55 -050089
Razvan Stefanescu44baaa42018-03-14 10:55:54 -050090struct ethsw_core;
91
Ioana Ciornei26d419f2021-03-10 14:14:41 +020092struct dpaa2_switch_fq {
93 struct ethsw_core *ethsw;
94 enum dpsw_queue_type type;
Ioana Ciornei2877e4f2021-03-10 14:14:42 +020095 struct dpaa2_io_store *store;
Ioana Ciornei04abc972021-03-10 14:14:43 +020096 struct dpaa2_io_notification_ctx nctx;
Ioana Ciornei0b1b7132021-03-10 14:14:44 +020097 struct napi_struct napi;
Ioana Ciornei26d419f2021-03-10 14:14:41 +020098 u32 fqid;
99};
100
Ioana Ciornei539dda32021-03-10 14:14:47 +0200101struct dpaa2_switch_fdb {
102 struct net_device *bridge_dev;
103 u16 fdb_id;
104 bool in_use;
105};
106
Ioana Ciornei11103182021-04-13 16:24:46 +0300107struct dpaa2_switch_acl_entry {
108 struct list_head list;
109 u16 prio;
110 unsigned long cookie;
111
112 struct dpsw_acl_entry_cfg cfg;
113 struct dpsw_acl_key key;
114};
115
Ioana Ciornei1b0f14b2021-04-13 16:24:44 +0300116struct dpaa2_switch_acl_tbl {
Ioana Ciornei11103182021-04-13 16:24:46 +0300117 struct list_head entries;
118 struct ethsw_core *ethsw;
119 u64 ports;
120
Ioana Ciornei1b0f14b2021-04-13 16:24:44 +0300121 u16 id;
122 u8 num_rules;
123 bool in_use;
124};
125
Ioana Ciornei11103182021-04-13 16:24:46 +0300126static inline bool
127dpaa2_switch_acl_tbl_is_full(struct dpaa2_switch_acl_tbl *acl_tbl)
128{
129 if ((acl_tbl->num_rules + DPAA2_ETHSW_PORT_DEFAULT_TRAPS) >=
130 DPAA2_ETHSW_PORT_MAX_ACL_ENTRIES)
131 return true;
132 return false;
133}
134
Razvan Stefanescu44baaa42018-03-14 10:55:54 -0500135/* Per port private data */
136struct ethsw_port_priv {
137 struct net_device *netdev;
138 u16 idx;
139 struct ethsw_core *ethsw_data;
140 u8 link_state;
141 u8 stp_state;
Razvan Stefanescu44baaa42018-03-14 10:55:54 -0500142
143 u8 vlans[VLAN_VID_MASK + 1];
144 u16 pvid;
Ioana Ciornei7fd94d82021-03-10 14:14:45 +0200145 u16 tx_qdid;
Ioana Ciornei539dda32021-03-10 14:14:47 +0200146
147 struct dpaa2_switch_fdb *fdb;
Ioana Ciorneib54eb092021-03-22 22:58:57 +0200148 bool bcast_flood;
Ioana Ciornei6253d5e2021-03-22 22:58:58 +0200149 bool ucast_flood;
Ioana Ciornei62734c72021-03-30 17:54:17 +0300150 bool learn_ena;
Ioana Ciornei90f07102021-03-30 17:54:16 +0300151
Ioana Ciornei1b0f14b2021-04-13 16:24:44 +0300152 struct dpaa2_switch_acl_tbl *acl_tbl;
Razvan Stefanescu44baaa42018-03-14 10:55:54 -0500153};
154
155/* Switch data */
156struct ethsw_core {
157 struct device *dev;
158 struct fsl_mc_io *mc_io;
159 u16 dpsw_handle;
160 struct dpsw_attr sw_attr;
Ioana Ciornei3b9c7022020-07-14 16:34:30 +0300161 u16 major, minor;
Ioana Ciornei240cb8d2020-07-14 16:34:31 +0300162 unsigned long features;
Razvan Stefanescu44baaa42018-03-14 10:55:54 -0500163 int dev_id;
164 struct ethsw_port_priv **ports;
Ioana Ciornei0b1b7132021-03-10 14:14:44 +0200165 struct iommu_domain *iommu_domain;
Razvan Stefanescu44baaa42018-03-14 10:55:54 -0500166
167 u8 vlans[VLAN_VID_MASK + 1];
Ioana Ciorneic5e648f2019-11-11 18:50:55 +0200168
Ioana Ciorneib8f64752019-11-11 18:50:58 +0200169 struct workqueue_struct *workqueue;
Ioana Ciornei26d419f2021-03-10 14:14:41 +0200170
171 struct dpaa2_switch_fq fq[DPAA2_SWITCH_RX_NUM_FQS];
Ioana Ciornei2877e4f2021-03-10 14:14:42 +0200172 struct fsl_mc_device *dpbp_dev;
Ioana Ciornei0b1b7132021-03-10 14:14:44 +0200173 int buf_count;
Ioana Ciornei2877e4f2021-03-10 14:14:42 +0200174 u16 bpid;
Ioana Ciornei0b1b7132021-03-10 14:14:44 +0200175 int napi_users;
Ioana Ciornei539dda32021-03-10 14:14:47 +0200176
177 struct dpaa2_switch_fdb *fdbs;
Ioana Ciornei1b0f14b2021-04-13 16:24:44 +0300178 struct dpaa2_switch_acl_tbl *acls;
Razvan Stefanescu44baaa42018-03-14 10:55:54 -0500179};
180
Ioana Ciornei11103182021-04-13 16:24:46 +0300181static inline int dpaa2_switch_get_index(struct ethsw_core *ethsw,
182 struct net_device *netdev)
183{
184 int i;
185
186 for (i = 0; i < ethsw->sw_attr.num_ifs; i++)
187 if (ethsw->ports[i]->netdev == netdev)
188 return ethsw->ports[i]->idx;
189
190 return -EINVAL;
191}
192
Ioana Ciornei26d419f2021-03-10 14:14:41 +0200193static inline bool dpaa2_switch_supports_cpu_traffic(struct ethsw_core *ethsw)
194{
195 if (ethsw->sw_attr.options & DPSW_OPT_CTRL_IF_DIS) {
196 dev_err(ethsw->dev, "Control Interface is disabled, cannot probe\n");
197 return false;
198 }
199
Ioana Ciornei539dda32021-03-10 14:14:47 +0200200 if (ethsw->sw_attr.flooding_cfg != DPSW_FLOODING_PER_FDB) {
201 dev_err(ethsw->dev, "Flooding domain is not per FDB, cannot probe\n");
202 return false;
203 }
204
205 if (ethsw->sw_attr.broadcast_cfg != DPSW_BROADCAST_PER_FDB) {
206 dev_err(ethsw->dev, "Broadcast domain is not per FDB, cannot probe\n");
207 return false;
208 }
209
210 if (ethsw->sw_attr.max_fdbs < ethsw->sw_attr.num_ifs) {
211 dev_err(ethsw->dev, "The number of FDBs is lower than the number of ports, cannot probe\n");
212 return false;
213 }
214
Ioana Ciornei26d419f2021-03-10 14:14:41 +0200215 return true;
216}
Ioana Ciornei539dda32021-03-10 14:14:47 +0200217
Ioana Ciornei16abb6a2021-03-10 14:14:48 +0200218bool dpaa2_switch_port_dev_check(const struct net_device *netdev);
Ioana Ciornei539dda32021-03-10 14:14:47 +0200219
Ioana Ciorneid6714072021-03-10 14:14:49 +0200220int dpaa2_switch_port_vlans_add(struct net_device *netdev,
221 const struct switchdev_obj_port_vlan *vlan);
222
223int dpaa2_switch_port_vlans_del(struct net_device *netdev,
224 const struct switchdev_obj_port_vlan *vlan);
225
Ioana Ciornei685b4802021-03-10 14:14:50 +0200226typedef int dpaa2_switch_fdb_cb_t(struct ethsw_port_priv *port_priv,
227 struct fdb_dump_entry *fdb_entry,
228 void *data);
Ioana Ciornei11103182021-04-13 16:24:46 +0300229
230/* TC offload */
231
232int dpaa2_switch_cls_flower_replace(struct dpaa2_switch_acl_tbl *acl_tbl,
233 struct flow_cls_offload *cls);
234
235int dpaa2_switch_cls_flower_destroy(struct dpaa2_switch_acl_tbl *acl_tbl,
236 struct flow_cls_offload *cls);
Ioana Ciornei4ba28c12021-04-13 16:24:47 +0300237
238int dpaa2_switch_cls_matchall_replace(struct dpaa2_switch_acl_tbl *acl_tbl,
239 struct tc_cls_matchall_offload *cls);
240
241int dpaa2_switch_cls_matchall_destroy(struct dpaa2_switch_acl_tbl *acl_tbl,
242 struct tc_cls_matchall_offload *cls);
Ioana Ciornei16617952021-04-13 16:24:48 +0300243
244int dpaa2_switch_acl_entry_add(struct dpaa2_switch_acl_tbl *acl_tbl,
245 struct dpaa2_switch_acl_entry *entry);
Razvan Stefanescu44baaa42018-03-14 10:55:54 -0500246#endif /* __ETHSW_H */