xref: /linux/drivers/net/dsa/netc/netc_main.c (revision 05b5ee610fbb8ca4ce9dc21299442aa827b38008)
1187fbae0SWei Fang // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2187fbae0SWei Fang /*
3187fbae0SWei Fang  * NXP NETC switch driver
4187fbae0SWei Fang  * Copyright 2025-2026 NXP
5187fbae0SWei Fang  */
6187fbae0SWei Fang 
746d64076SWei Fang #include <linux/clk.h>
8187fbae0SWei Fang #include <linux/etherdevice.h>
9187fbae0SWei Fang #include <linux/fsl/enetc_mdio.h>
1046d64076SWei Fang #include <linux/if_bridge.h>
11187fbae0SWei Fang #include <linux/if_vlan.h>
12187fbae0SWei Fang #include <linux/of_mdio.h>
13187fbae0SWei Fang 
14187fbae0SWei Fang #include "netc_switch.h"
15187fbae0SWei Fang 
1646d64076SWei Fang static struct netc_fdb_entry *
1746d64076SWei Fang netc_lookup_fdb_entry(struct netc_switch *priv,
1846d64076SWei Fang 		      const unsigned char *addr,
1946d64076SWei Fang 		      u16 vid)
2046d64076SWei Fang {
2146d64076SWei Fang 	struct netc_fdb_entry *entry;
2246d64076SWei Fang 
2346d64076SWei Fang 	hlist_for_each_entry(entry, &priv->fdb_list, node)
2446d64076SWei Fang 		if (ether_addr_equal(entry->keye.mac_addr, addr) &&
2546d64076SWei Fang 		    le16_to_cpu(entry->keye.fid) == vid)
2646d64076SWei Fang 			return entry;
2746d64076SWei Fang 
2846d64076SWei Fang 	return NULL;
2946d64076SWei Fang }
3046d64076SWei Fang 
3146d64076SWei Fang static void netc_destroy_fdb_list(struct netc_switch *priv)
3246d64076SWei Fang {
3346d64076SWei Fang 	struct netc_fdb_entry *entry;
3446d64076SWei Fang 	struct hlist_node *tmp;
3546d64076SWei Fang 
3646d64076SWei Fang 	hlist_for_each_entry_safe(entry, tmp, &priv->fdb_list, node)
3746d64076SWei Fang 		netc_del_fdb_entry(entry);
3846d64076SWei Fang }
3946d64076SWei Fang 
4084b4a3b3SWei Fang static struct netc_vlan_entry *
4184b4a3b3SWei Fang netc_lookup_vlan_entry(struct netc_switch *priv, u16 vid)
4284b4a3b3SWei Fang {
4384b4a3b3SWei Fang 	struct netc_vlan_entry *entry;
4484b4a3b3SWei Fang 
4584b4a3b3SWei Fang 	hlist_for_each_entry(entry, &priv->vlan_list, node)
4684b4a3b3SWei Fang 		if (entry->vid == vid)
4784b4a3b3SWei Fang 			return entry;
4884b4a3b3SWei Fang 
4984b4a3b3SWei Fang 	return NULL;
5084b4a3b3SWei Fang }
5184b4a3b3SWei Fang 
5284b4a3b3SWei Fang static void netc_destroy_vlan_list(struct netc_switch *priv)
5384b4a3b3SWei Fang {
5484b4a3b3SWei Fang 	struct netc_vlan_entry *entry;
5584b4a3b3SWei Fang 	struct hlist_node *tmp;
5684b4a3b3SWei Fang 
5784b4a3b3SWei Fang 	hlist_for_each_entry_safe(entry, tmp, &priv->vlan_list, node)
5884b4a3b3SWei Fang 		netc_del_vlan_entry(entry);
5984b4a3b3SWei Fang }
6084b4a3b3SWei Fang 
61187fbae0SWei Fang static enum dsa_tag_protocol
62187fbae0SWei Fang netc_get_tag_protocol(struct dsa_switch *ds, int port,
63187fbae0SWei Fang 		      enum dsa_tag_protocol mprot)
64187fbae0SWei Fang {
65187fbae0SWei Fang 	return DSA_TAG_PROTO_NETC;
66187fbae0SWei Fang }
67187fbae0SWei Fang 
68187fbae0SWei Fang static void netc_port_rmw(struct netc_port *np, u32 reg,
69187fbae0SWei Fang 			  u32 mask, u32 val)
70187fbae0SWei Fang {
71187fbae0SWei Fang 	u32 old, new;
72187fbae0SWei Fang 
73187fbae0SWei Fang 	WARN_ON((mask | val) != mask);
74187fbae0SWei Fang 
75187fbae0SWei Fang 	old = netc_port_rd(np, reg);
76187fbae0SWei Fang 	new = (old & ~mask) | val;
77187fbae0SWei Fang 	if (new == old)
78187fbae0SWei Fang 		return;
79187fbae0SWei Fang 
80187fbae0SWei Fang 	netc_port_wr(np, reg, new);
81187fbae0SWei Fang }
82187fbae0SWei Fang 
83187fbae0SWei Fang static void netc_mac_port_wr(struct netc_port *np, u32 reg, u32 val)
84187fbae0SWei Fang {
85187fbae0SWei Fang 	if (is_netc_pseudo_port(np))
86187fbae0SWei Fang 		return;
87187fbae0SWei Fang 
88187fbae0SWei Fang 	netc_port_wr(np, reg, val);
89187fbae0SWei Fang 	if (np->caps.pmac)
90187fbae0SWei Fang 		netc_port_wr(np, reg + NETC_PMAC_OFFSET, val);
91187fbae0SWei Fang }
92187fbae0SWei Fang 
93bbe97e34SWei Fang /* netc_mac_port_rmw() is used to synchronize the configurations of eMAC
94bbe97e34SWei Fang  * and pMAC to maintain consistency. This function should not be used if
95bbe97e34SWei Fang  * differentiated settings are required.
96bbe97e34SWei Fang  */
97bbe97e34SWei Fang static void netc_mac_port_rmw(struct netc_port *np, u32 reg,
98bbe97e34SWei Fang 			      u32 mask, u32 val)
99bbe97e34SWei Fang {
100bbe97e34SWei Fang 	u32 old, new;
101bbe97e34SWei Fang 
102bbe97e34SWei Fang 	if (is_netc_pseudo_port(np))
103bbe97e34SWei Fang 		return;
104bbe97e34SWei Fang 
105bbe97e34SWei Fang 	WARN_ON((mask | val) != mask);
106bbe97e34SWei Fang 
107bbe97e34SWei Fang 	old = netc_port_rd(np, reg);
108bbe97e34SWei Fang 	new = (old & ~mask) | val;
109bbe97e34SWei Fang 	if (new == old)
110bbe97e34SWei Fang 		return;
111bbe97e34SWei Fang 
112bbe97e34SWei Fang 	netc_port_wr(np, reg, new);
113bbe97e34SWei Fang 	if (np->caps.pmac)
114bbe97e34SWei Fang 		netc_port_wr(np, reg + NETC_PMAC_OFFSET, new);
115bbe97e34SWei Fang }
116bbe97e34SWei Fang 
117187fbae0SWei Fang static void netc_port_get_capability(struct netc_port *np)
118187fbae0SWei Fang {
119187fbae0SWei Fang 	u32 val;
120187fbae0SWei Fang 
121187fbae0SWei Fang 	val = netc_port_rd(np, NETC_PMCAPR);
122187fbae0SWei Fang 	if (val & PMCAPR_HD)
123187fbae0SWei Fang 		np->caps.half_duplex = true;
124187fbae0SWei Fang 
125187fbae0SWei Fang 	if (FIELD_GET(PMCAPR_FP, val) == FP_SUPPORT)
126187fbae0SWei Fang 		np->caps.pmac = true;
127187fbae0SWei Fang 
128187fbae0SWei Fang 	val = netc_port_rd(np, NETC_PCAPR);
129187fbae0SWei Fang 	if (val & PCAPR_LINK_TYPE)
130187fbae0SWei Fang 		np->caps.pseudo_link = true;
131187fbae0SWei Fang }
132187fbae0SWei Fang 
13346d64076SWei Fang static int netc_port_get_info_from_dt(struct netc_port *np,
13446d64076SWei Fang 				      struct device_node *node,
13546d64076SWei Fang 				      struct device *dev)
13646d64076SWei Fang {
13746d64076SWei Fang 	if (of_find_property(node, "clock-names", NULL)) {
13846d64076SWei Fang 		np->ref_clk = devm_get_clk_from_child(dev, node, "ref");
13946d64076SWei Fang 		if (IS_ERR(np->ref_clk)) {
14046d64076SWei Fang 			dev_err(dev, "Port %d cannot get reference clock\n",
14146d64076SWei Fang 				np->dp->index);
14246d64076SWei Fang 			return PTR_ERR(np->ref_clk);
14346d64076SWei Fang 		}
14446d64076SWei Fang 	}
14546d64076SWei Fang 
14646d64076SWei Fang 	return 0;
14746d64076SWei Fang }
14846d64076SWei Fang 
149187fbae0SWei Fang static int netc_port_create_emdio_bus(struct netc_port *np,
150187fbae0SWei Fang 				      struct device_node *node)
151187fbae0SWei Fang {
152187fbae0SWei Fang 	struct netc_switch *priv = np->switch_priv;
153187fbae0SWei Fang 	struct enetc_mdio_priv *mdio_priv;
154187fbae0SWei Fang 	struct device *dev = priv->dev;
155187fbae0SWei Fang 	struct enetc_hw *hw;
156187fbae0SWei Fang 	struct mii_bus *bus;
157187fbae0SWei Fang 	int err;
158187fbae0SWei Fang 
159187fbae0SWei Fang 	hw = enetc_hw_alloc(dev, np->iobase);
160187fbae0SWei Fang 	if (IS_ERR(hw))
161187fbae0SWei Fang 		return dev_err_probe(dev, PTR_ERR(hw),
162187fbae0SWei Fang 				     "Failed to allocate enetc_hw\n");
163187fbae0SWei Fang 
164187fbae0SWei Fang 	bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
165187fbae0SWei Fang 	if (!bus)
166187fbae0SWei Fang 		return -ENOMEM;
167187fbae0SWei Fang 
168187fbae0SWei Fang 	bus->name = "NXP NETC switch external MDIO Bus";
169187fbae0SWei Fang 	bus->read = enetc_mdio_read_c22;
170187fbae0SWei Fang 	bus->write = enetc_mdio_write_c22;
171187fbae0SWei Fang 	bus->read_c45 = enetc_mdio_read_c45;
172187fbae0SWei Fang 	bus->write_c45 = enetc_mdio_write_c45;
173187fbae0SWei Fang 	bus->parent = dev;
174187fbae0SWei Fang 	mdio_priv = bus->priv;
175187fbae0SWei Fang 	mdio_priv->hw = hw;
176187fbae0SWei Fang 	mdio_priv->mdio_base = NETC_EMDIO_BASE;
177187fbae0SWei Fang 	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-p%d-emdio",
178187fbae0SWei Fang 		 dev_name(dev), np->dp->index);
179187fbae0SWei Fang 
180187fbae0SWei Fang 	err = devm_of_mdiobus_register(dev, bus, node);
181187fbae0SWei Fang 	if (err)
182187fbae0SWei Fang 		return dev_err_probe(dev, err,
183187fbae0SWei Fang 				     "Cannot register EMDIO bus\n");
184187fbae0SWei Fang 
185187fbae0SWei Fang 	np->emdio = bus;
186187fbae0SWei Fang 
187187fbae0SWei Fang 	return 0;
188187fbae0SWei Fang }
189187fbae0SWei Fang 
190187fbae0SWei Fang static int netc_port_create_mdio_bus(struct netc_port *np,
191187fbae0SWei Fang 				     struct device_node *node)
192187fbae0SWei Fang {
193187fbae0SWei Fang 	struct device_node *mdio_node;
194187fbae0SWei Fang 	int err;
195187fbae0SWei Fang 
196187fbae0SWei Fang 	mdio_node = of_get_child_by_name(node, "mdio");
197187fbae0SWei Fang 	if (mdio_node) {
198187fbae0SWei Fang 		err = netc_port_create_emdio_bus(np, mdio_node);
199187fbae0SWei Fang 		of_node_put(mdio_node);
200187fbae0SWei Fang 		if (err)
201187fbae0SWei Fang 			return err;
202187fbae0SWei Fang 	}
203187fbae0SWei Fang 
204187fbae0SWei Fang 	return 0;
205187fbae0SWei Fang }
206187fbae0SWei Fang 
207187fbae0SWei Fang static int netc_init_switch_id(struct netc_switch *priv)
208187fbae0SWei Fang {
209187fbae0SWei Fang 	struct netc_switch_regs *regs = &priv->regs;
210187fbae0SWei Fang 	struct dsa_switch *ds = priv->ds;
211187fbae0SWei Fang 
212187fbae0SWei Fang 	/* The value of 0 is reserved for the VEPA switch and cannot
213187fbae0SWei Fang 	 * be used. So 'dsa,member' is a required property for NETC
214187fbae0SWei Fang 	 * switch, the member is used to specify the switch ID, which
215187fbae0SWei Fang 	 * cannot be zero. This way, the hardware switch ID and the
216187fbae0SWei Fang 	 * software switch ID are consistent.
217187fbae0SWei Fang 	 */
218187fbae0SWei Fang 	if (ds->index > FIELD_MAX(SWCR_SWID) || !ds->index) {
219187fbae0SWei Fang 		dev_err(priv->dev, "Switch index %d out of range\n",
220187fbae0SWei Fang 			ds->index);
221187fbae0SWei Fang 		return -ERANGE;
222187fbae0SWei Fang 	}
223187fbae0SWei Fang 
224187fbae0SWei Fang 	netc_base_wr(regs, NETC_SWCR, ds->index);
225187fbae0SWei Fang 
226187fbae0SWei Fang 	return 0;
227187fbae0SWei Fang }
228187fbae0SWei Fang 
22946d64076SWei Fang static void netc_get_switch_capabilities(struct netc_switch *priv)
23046d64076SWei Fang {
23146d64076SWei Fang 	struct netc_switch_regs *regs = &priv->regs;
23246d64076SWei Fang 	u32 val;
23346d64076SWei Fang 
23446d64076SWei Fang 	val = netc_base_rd(regs, NETC_HTMCAPR);
23546d64076SWei Fang 	priv->htmcapr_num_words = FIELD_GET(HTMCAPR_NUM_WORDS, val);
236a5ccb7f5SWei Fang 
237a5ccb7f5SWei Fang 	val = netc_base_rd(regs, NETC_BPCAPR);
238a5ccb7f5SWei Fang 	priv->num_bp = FIELD_GET(BPCAPR_NUM_BP, val);
23946d64076SWei Fang }
24046d64076SWei Fang 
241187fbae0SWei Fang static int netc_init_all_ports(struct netc_switch *priv)
242187fbae0SWei Fang {
243187fbae0SWei Fang 	struct device *dev = priv->dev;
244187fbae0SWei Fang 	struct netc_port *np;
245187fbae0SWei Fang 	struct dsa_port *dp;
24684b4a3b3SWei Fang 	int ett_offset = 0;
247187fbae0SWei Fang 	int err;
248187fbae0SWei Fang 
249187fbae0SWei Fang 	priv->ports = devm_kcalloc(dev, priv->info->num_ports,
250187fbae0SWei Fang 				   sizeof(struct netc_port *),
251187fbae0SWei Fang 				   GFP_KERNEL);
252187fbae0SWei Fang 	if (!priv->ports)
253187fbae0SWei Fang 		return -ENOMEM;
254187fbae0SWei Fang 
255187fbae0SWei Fang 	/* Some DSA interfaces may set the port even it is disabled, such
256187fbae0SWei Fang 	 * as .port_disable(), .port_stp_state_set() and so on. To avoid
257187fbae0SWei Fang 	 * crash caused by accessing NULL port pointer, each port is
258187fbae0SWei Fang 	 * allocated its own memory. Otherwise, we need to check whether
259187fbae0SWei Fang 	 * the port pointer is NULL in these interfaces. The latter is
260187fbae0SWei Fang 	 * difficult for us to cover.
261187fbae0SWei Fang 	 */
262187fbae0SWei Fang 	for (int i = 0; i < priv->info->num_ports; i++) {
263187fbae0SWei Fang 		np = devm_kzalloc(dev, sizeof(*np), GFP_KERNEL);
264187fbae0SWei Fang 		if (!np)
265187fbae0SWei Fang 			return -ENOMEM;
266187fbae0SWei Fang 
267187fbae0SWei Fang 		np->switch_priv = priv;
268187fbae0SWei Fang 		np->iobase = priv->regs.port + PORT_IOBASE(i);
269187fbae0SWei Fang 		netc_port_get_capability(np);
270187fbae0SWei Fang 		priv->ports[i] = np;
271187fbae0SWei Fang 	}
272187fbae0SWei Fang 
273187fbae0SWei Fang 	dsa_switch_for_each_available_port(dp, priv->ds) {
274187fbae0SWei Fang 		np = priv->ports[dp->index];
275187fbae0SWei Fang 		np->dp = dp;
27684b4a3b3SWei Fang 		np->ett_offset = ett_offset++;
27784b4a3b3SWei Fang 		priv->port_bitmap |= BIT(dp->index);
278187fbae0SWei Fang 
27946d64076SWei Fang 		err = netc_port_get_info_from_dt(np, dp->dn, dev);
28046d64076SWei Fang 		if (err)
28146d64076SWei Fang 			return err;
28246d64076SWei Fang 
283187fbae0SWei Fang 		if (dsa_port_is_user(dp)) {
284187fbae0SWei Fang 			err = netc_port_create_mdio_bus(np, dp->dn);
285187fbae0SWei Fang 			if (err) {
286187fbae0SWei Fang 				dev_err(dev, "Failed to create MDIO bus\n");
287187fbae0SWei Fang 				return err;
288187fbae0SWei Fang 			}
289187fbae0SWei Fang 		}
290187fbae0SWei Fang 	}
291187fbae0SWei Fang 
292187fbae0SWei Fang 	return 0;
293187fbae0SWei Fang }
294187fbae0SWei Fang 
295187fbae0SWei Fang static void netc_init_ntmp_tbl_versions(struct netc_switch *priv)
296187fbae0SWei Fang {
297187fbae0SWei Fang 	struct ntmp_user *ntmp = &priv->ntmp;
298187fbae0SWei Fang 
299187fbae0SWei Fang 	/* All tables default to version 0 */
300187fbae0SWei Fang 	memset(&ntmp->tbl, 0, sizeof(ntmp->tbl));
301187fbae0SWei Fang }
302187fbae0SWei Fang 
303187fbae0SWei Fang static int netc_init_all_cbdrs(struct netc_switch *priv)
304187fbae0SWei Fang {
305187fbae0SWei Fang 	struct netc_switch_regs *regs = &priv->regs;
306187fbae0SWei Fang 	struct ntmp_user *ntmp = &priv->ntmp;
307187fbae0SWei Fang 	int i, err;
308187fbae0SWei Fang 
309187fbae0SWei Fang 	ntmp->cbdr_num = NETC_CBDR_NUM;
310187fbae0SWei Fang 	ntmp->dev = priv->dev;
311187fbae0SWei Fang 	ntmp->ring = devm_kcalloc(ntmp->dev, ntmp->cbdr_num,
312187fbae0SWei Fang 				  sizeof(struct netc_cbdr),
313187fbae0SWei Fang 				  GFP_KERNEL);
314187fbae0SWei Fang 	if (!ntmp->ring)
315187fbae0SWei Fang 		return -ENOMEM;
316187fbae0SWei Fang 
317187fbae0SWei Fang 	for (i = 0; i < ntmp->cbdr_num; i++) {
318187fbae0SWei Fang 		struct netc_cbdr *cbdr = &ntmp->ring[i];
319187fbae0SWei Fang 		struct netc_cbdr_regs cbdr_regs;
320187fbae0SWei Fang 
321187fbae0SWei Fang 		cbdr_regs.pir = regs->base + NETC_CBDRPIR(i);
322187fbae0SWei Fang 		cbdr_regs.cir = regs->base + NETC_CBDRCIR(i);
323187fbae0SWei Fang 		cbdr_regs.mr = regs->base + NETC_CBDRMR(i);
324187fbae0SWei Fang 		cbdr_regs.bar0 = regs->base + NETC_CBDRBAR0(i);
325187fbae0SWei Fang 		cbdr_regs.bar1 = regs->base + NETC_CBDRBAR1(i);
326187fbae0SWei Fang 		cbdr_regs.lenr = regs->base + NETC_CBDRLENR(i);
327187fbae0SWei Fang 
328187fbae0SWei Fang 		err = ntmp_init_cbdr(cbdr, ntmp->dev, &cbdr_regs);
329187fbae0SWei Fang 		if (err)
330187fbae0SWei Fang 			goto free_cbdrs;
331187fbae0SWei Fang 	}
332187fbae0SWei Fang 
333187fbae0SWei Fang 	return 0;
334187fbae0SWei Fang 
335187fbae0SWei Fang free_cbdrs:
336187fbae0SWei Fang 	for (i--; i >= 0; i--)
337187fbae0SWei Fang 		ntmp_free_cbdr(&ntmp->ring[i]);
338187fbae0SWei Fang 
339187fbae0SWei Fang 	return err;
340187fbae0SWei Fang }
341187fbae0SWei Fang 
342187fbae0SWei Fang static void netc_remove_all_cbdrs(struct netc_switch *priv)
343187fbae0SWei Fang {
344187fbae0SWei Fang 	struct ntmp_user *ntmp = &priv->ntmp;
345187fbae0SWei Fang 
346187fbae0SWei Fang 	for (int i = 0; i < NETC_CBDR_NUM; i++)
347187fbae0SWei Fang 		ntmp_free_cbdr(&ntmp->ring[i]);
348187fbae0SWei Fang }
349187fbae0SWei Fang 
3501a58ae73SWei Fang static u32 netc_num_available_ports(struct netc_switch *priv)
3511a58ae73SWei Fang {
3521a58ae73SWei Fang 	struct dsa_port *dp;
3531a58ae73SWei Fang 	u32 num_ports = 0;
3541a58ae73SWei Fang 
3551a58ae73SWei Fang 	dsa_switch_for_each_available_port(dp, priv->ds)
3561a58ae73SWei Fang 		num_ports++;
3571a58ae73SWei Fang 
3581a58ae73SWei Fang 	return num_ports;
3591a58ae73SWei Fang }
3601a58ae73SWei Fang 
3611a58ae73SWei Fang static int netc_init_ntmp_bitmap_sizes(struct netc_switch *priv)
3621a58ae73SWei Fang {
3631a58ae73SWei Fang 	u32 num_ports = netc_num_available_ports(priv);
3641a58ae73SWei Fang 	struct netc_switch_regs *regs = &priv->regs;
3651a58ae73SWei Fang 	struct ntmp_user *ntmp = &priv->ntmp;
3661a58ae73SWei Fang 	u32 val;
3671a58ae73SWei Fang 
3681a58ae73SWei Fang 	if (!num_ports)
3691a58ae73SWei Fang 		return -EINVAL;
3701a58ae73SWei Fang 
3711a58ae73SWei Fang 	val = netc_base_rd(regs, NETC_ETTCAPR);
3721a58ae73SWei Fang 	ntmp->ett_bitmap_size = NETC_GET_NUM_ENTRIES(val) / num_ports;
3731a58ae73SWei Fang 	if (!ntmp->ett_bitmap_size)
3741a58ae73SWei Fang 		return -EINVAL;
3751a58ae73SWei Fang 
3761a58ae73SWei Fang 	val = netc_base_rd(regs, NETC_ECTCAPR);
3771a58ae73SWei Fang 	ntmp->ect_bitmap_size = NETC_GET_NUM_ENTRIES(val) / num_ports;
3781a58ae73SWei Fang 	if (!ntmp->ect_bitmap_size)
3791a58ae73SWei Fang 		return -EINVAL;
3801a58ae73SWei Fang 
3811a58ae73SWei Fang 	return 0;
3821a58ae73SWei Fang }
3831a58ae73SWei Fang 
3841a58ae73SWei Fang static int netc_init_ntmp_bitmaps(struct netc_switch *priv)
3851a58ae73SWei Fang {
3861a58ae73SWei Fang 	struct ntmp_user *ntmp = &priv->ntmp;
3871a58ae73SWei Fang 
3881a58ae73SWei Fang 	ntmp->ett_gid_bitmap = bitmap_zalloc(ntmp->ett_bitmap_size,
3891a58ae73SWei Fang 					     GFP_KERNEL);
3901a58ae73SWei Fang 	if (!ntmp->ett_gid_bitmap)
3911a58ae73SWei Fang 		return -ENOMEM;
3921a58ae73SWei Fang 
3931a58ae73SWei Fang 	ntmp->ect_gid_bitmap = bitmap_zalloc(ntmp->ect_bitmap_size,
3941a58ae73SWei Fang 					     GFP_KERNEL);
3951a58ae73SWei Fang 	if (!ntmp->ect_gid_bitmap)
3961a58ae73SWei Fang 		goto free_ett_gid_bitmap;
3971a58ae73SWei Fang 
3981a58ae73SWei Fang 	return 0;
3991a58ae73SWei Fang 
4001a58ae73SWei Fang free_ett_gid_bitmap:
4011a58ae73SWei Fang 	bitmap_free(ntmp->ett_gid_bitmap);
4021a58ae73SWei Fang 	ntmp->ett_gid_bitmap = NULL;
4031a58ae73SWei Fang 
4041a58ae73SWei Fang 	return -ENOMEM;
4051a58ae73SWei Fang }
4061a58ae73SWei Fang 
4071a58ae73SWei Fang static void netc_free_ntmp_bitmaps(struct netc_switch *priv)
4081a58ae73SWei Fang {
4091a58ae73SWei Fang 	struct ntmp_user *ntmp = &priv->ntmp;
4101a58ae73SWei Fang 
4111a58ae73SWei Fang 	bitmap_free(ntmp->ect_gid_bitmap);
4121a58ae73SWei Fang 	ntmp->ect_gid_bitmap = NULL;
4131a58ae73SWei Fang 
4141a58ae73SWei Fang 	bitmap_free(ntmp->ett_gid_bitmap);
4151a58ae73SWei Fang 	ntmp->ett_gid_bitmap = NULL;
4161a58ae73SWei Fang }
4171a58ae73SWei Fang 
418187fbae0SWei Fang static int netc_init_ntmp_user(struct netc_switch *priv)
419187fbae0SWei Fang {
4201a58ae73SWei Fang 	int err;
4211a58ae73SWei Fang 
422187fbae0SWei Fang 	netc_init_ntmp_tbl_versions(priv);
423187fbae0SWei Fang 
4241a58ae73SWei Fang 	err = netc_init_ntmp_bitmap_sizes(priv);
4251a58ae73SWei Fang 	if (err)
4261a58ae73SWei Fang 		return err;
4271a58ae73SWei Fang 
4281a58ae73SWei Fang 	err = netc_init_ntmp_bitmaps(priv);
4291a58ae73SWei Fang 	if (err)
4301a58ae73SWei Fang 		return err;
4311a58ae73SWei Fang 
4321a58ae73SWei Fang 	err = netc_init_all_cbdrs(priv);
4331a58ae73SWei Fang 	if (err)
4341a58ae73SWei Fang 		goto free_ntmp_bitmaps;
4351a58ae73SWei Fang 
4361a58ae73SWei Fang 	return 0;
4371a58ae73SWei Fang 
4381a58ae73SWei Fang free_ntmp_bitmaps:
4391a58ae73SWei Fang 	netc_free_ntmp_bitmaps(priv);
4401a58ae73SWei Fang 
4411a58ae73SWei Fang 	return err;
442187fbae0SWei Fang }
443187fbae0SWei Fang 
444187fbae0SWei Fang static void netc_free_ntmp_user(struct netc_switch *priv)
445187fbae0SWei Fang {
446187fbae0SWei Fang 	netc_remove_all_cbdrs(priv);
4471a58ae73SWei Fang 	netc_free_ntmp_bitmaps(priv);
448187fbae0SWei Fang }
449187fbae0SWei Fang 
450*05b5ee61SWei Fang static void netc_clean_fdbt_ageing_entries(struct work_struct *work)
451*05b5ee61SWei Fang {
452*05b5ee61SWei Fang 	struct delayed_work *dwork = to_delayed_work(work);
453*05b5ee61SWei Fang 	struct netc_switch *priv;
454*05b5ee61SWei Fang 
455*05b5ee61SWei Fang 	priv = container_of(dwork, struct netc_switch, fdbt_ageing_work);
456*05b5ee61SWei Fang 
457*05b5ee61SWei Fang 	/* Update the activity element in FDB table */
458*05b5ee61SWei Fang 	mutex_lock(&priv->fdbt_lock);
459*05b5ee61SWei Fang 	ntmp_fdbt_update_activity_element(&priv->ntmp);
460*05b5ee61SWei Fang 	/* Delete the ageing entries after the activity element is updated */
461*05b5ee61SWei Fang 	ntmp_fdbt_delete_ageing_entries(&priv->ntmp, NETC_FDBT_AGEING_THRESH);
462*05b5ee61SWei Fang 	mutex_unlock(&priv->fdbt_lock);
463*05b5ee61SWei Fang 
464*05b5ee61SWei Fang 	if (atomic_read(&priv->br_cnt))
465*05b5ee61SWei Fang 		schedule_delayed_work(&priv->fdbt_ageing_work,
466*05b5ee61SWei Fang 				      READ_ONCE(priv->fdbt_ageing_delay));
467*05b5ee61SWei Fang }
468*05b5ee61SWei Fang 
469187fbae0SWei Fang static void netc_switch_dos_default_config(struct netc_switch *priv)
470187fbae0SWei Fang {
471187fbae0SWei Fang 	struct netc_switch_regs *regs = &priv->regs;
472187fbae0SWei Fang 	u32 val;
473187fbae0SWei Fang 
474187fbae0SWei Fang 	val = DOSL2CR_SAMEADDR | DOSL2CR_MSAMCC;
475187fbae0SWei Fang 	netc_base_wr(regs, NETC_DOSL2CR, val);
476187fbae0SWei Fang 
477187fbae0SWei Fang 	val = DOSL3CR_SAMEADDR | DOSL3CR_IPSAMCC;
478187fbae0SWei Fang 	netc_base_wr(regs, NETC_DOSL3CR, val);
479187fbae0SWei Fang }
480187fbae0SWei Fang 
481187fbae0SWei Fang static void netc_switch_vfht_default_config(struct netc_switch *priv)
482187fbae0SWei Fang {
483187fbae0SWei Fang 	struct netc_switch_regs *regs = &priv->regs;
484187fbae0SWei Fang 	u32 val;
485187fbae0SWei Fang 
486187fbae0SWei Fang 	val = netc_base_rd(regs, NETC_VFHTDECR2);
487187fbae0SWei Fang 
488187fbae0SWei Fang 	/* If no match is found in the VLAN Filter table, then VFHTDECR2[MLO]
489187fbae0SWei Fang 	 * will take effect. VFHTDECR2[MLO] is set to "Software MAC learning
490187fbae0SWei Fang 	 * secure" by default. Notice BPCR[MLO] will override VFHTDECR2[MLO]
491187fbae0SWei Fang 	 * if its value is not zero.
492187fbae0SWei Fang 	 */
493187fbae0SWei Fang 	val = u32_replace_bits(val, MLO_SW_SEC, VFHTDECR2_MLO);
494187fbae0SWei Fang 	val = u32_replace_bits(val, MFO_NO_MATCH_DISCARD, VFHTDECR2_MFO);
495187fbae0SWei Fang 	netc_base_wr(regs, NETC_VFHTDECR2, val);
496187fbae0SWei Fang }
497187fbae0SWei Fang 
498187fbae0SWei Fang static void netc_port_set_max_frame_size(struct netc_port *np,
499187fbae0SWei Fang 					 u32 max_frame_size)
500187fbae0SWei Fang {
501187fbae0SWei Fang 	netc_mac_port_wr(np, NETC_PM_MAXFRM(0),
502187fbae0SWei Fang 			 max_frame_size & PM_MAXFRAM);
503187fbae0SWei Fang }
504187fbae0SWei Fang 
505187fbae0SWei Fang static void netc_switch_fixed_config(struct netc_switch *priv)
506187fbae0SWei Fang {
507187fbae0SWei Fang 	netc_switch_dos_default_config(priv);
508187fbae0SWei Fang 	netc_switch_vfht_default_config(priv);
509187fbae0SWei Fang }
510187fbae0SWei Fang 
511187fbae0SWei Fang static void netc_port_set_tc_max_sdu(struct netc_port *np,
512187fbae0SWei Fang 				     int tc, u32 max_sdu)
513187fbae0SWei Fang {
514187fbae0SWei Fang 	u32 val = FIELD_PREP(PTCTMSDUR_MAXSDU, max_sdu) |
515187fbae0SWei Fang 		  FIELD_PREP(PTCTMSDUR_SDU_TYPE, SDU_TYPE_MPDU);
516187fbae0SWei Fang 
517187fbae0SWei Fang 	netc_port_wr(np, NETC_PTCTMSDUR(tc), val);
518187fbae0SWei Fang }
519187fbae0SWei Fang 
520187fbae0SWei Fang static void netc_port_set_all_tc_msdu(struct netc_port *np)
521187fbae0SWei Fang {
522187fbae0SWei Fang 	for (int tc = 0; tc < NETC_TC_NUM; tc++)
523187fbae0SWei Fang 		netc_port_set_tc_max_sdu(np, tc, NETC_MAX_FRAME_LEN);
524187fbae0SWei Fang }
525187fbae0SWei Fang 
526187fbae0SWei Fang static void netc_port_set_mlo(struct netc_port *np, enum netc_mlo mlo)
527187fbae0SWei Fang {
528187fbae0SWei Fang 	netc_port_rmw(np, NETC_BPCR, BPCR_MLO, FIELD_PREP(BPCR_MLO, mlo));
529187fbae0SWei Fang }
530187fbae0SWei Fang 
531751aa5a5SWei Fang static void netc_port_set_pvid(struct netc_port *np, u16 pvid)
532751aa5a5SWei Fang {
533751aa5a5SWei Fang 	netc_port_rmw(np, NETC_BPDVR, BPDVR_VID, pvid);
534751aa5a5SWei Fang }
535751aa5a5SWei Fang 
536751aa5a5SWei Fang static void netc_port_set_vlan_aware(struct netc_port *np, bool aware)
537751aa5a5SWei Fang {
538751aa5a5SWei Fang 	netc_port_rmw(np, NETC_BPDVR, BPDVR_RXVAM,
539751aa5a5SWei Fang 		      aware ? 0 : BPDVR_RXVAM);
540751aa5a5SWei Fang }
541751aa5a5SWei Fang 
542187fbae0SWei Fang static void netc_port_fixed_config(struct netc_port *np)
543187fbae0SWei Fang {
544187fbae0SWei Fang 	/* Default IPV and DR setting */
545187fbae0SWei Fang 	netc_port_rmw(np, NETC_PQOSMR, PQOSMR_VS | PQOSMR_VE,
546187fbae0SWei Fang 		      PQOSMR_VS | PQOSMR_VE);
547187fbae0SWei Fang 
548187fbae0SWei Fang 	/* Enable L2 and L3 DOS */
549187fbae0SWei Fang 	netc_port_rmw(np, NETC_PCR, PCR_L2DOSE | PCR_L3DOSE,
550187fbae0SWei Fang 		      PCR_L2DOSE | PCR_L3DOSE);
551a5ccb7f5SWei Fang 
552a5ccb7f5SWei Fang 	/* Set the quanta value of TX PAUSE frame */
553a5ccb7f5SWei Fang 	netc_mac_port_wr(np, NETC_PM_PAUSE_QUANTA(0), NETC_PAUSE_QUANTA);
554a5ccb7f5SWei Fang 
555a5ccb7f5SWei Fang 	/* When a quanta timer counts down and reaches this value,
556a5ccb7f5SWei Fang 	 * the MAC sends a refresh PAUSE frame with the programmed
557a5ccb7f5SWei Fang 	 * full quanta value if a pause condition still exists.
558a5ccb7f5SWei Fang 	 */
559a5ccb7f5SWei Fang 	netc_mac_port_wr(np, NETC_PM_PAUSE_THRESH(0), NETC_PAUSE_THRESH);
560187fbae0SWei Fang }
561187fbae0SWei Fang 
562187fbae0SWei Fang static void netc_port_default_config(struct netc_port *np)
563187fbae0SWei Fang {
564187fbae0SWei Fang 	netc_port_fixed_config(np);
565187fbae0SWei Fang 
566187fbae0SWei Fang 	/* Default VLAN unaware */
567751aa5a5SWei Fang 	netc_port_set_vlan_aware(np, false);
568187fbae0SWei Fang 
569187fbae0SWei Fang 	if (dsa_port_is_cpu(np->dp))
570187fbae0SWei Fang 		/* For CPU port, source port pruning is disabled */
571187fbae0SWei Fang 		netc_port_rmw(np, NETC_BPCR, BPCR_SRCPRND, BPCR_SRCPRND);
572187fbae0SWei Fang 	else
573187fbae0SWei Fang 		netc_port_set_mlo(np, MLO_DISABLE);
574187fbae0SWei Fang 
575187fbae0SWei Fang 	netc_port_set_max_frame_size(np, NETC_MAX_FRAME_LEN);
576187fbae0SWei Fang 	netc_port_set_all_tc_msdu(np);
577187fbae0SWei Fang }
578187fbae0SWei Fang 
57946d64076SWei Fang static u32 netc_available_port_bitmap(struct netc_switch *priv)
58046d64076SWei Fang {
58146d64076SWei Fang 	struct dsa_port *dp;
58246d64076SWei Fang 	u32 bitmap = 0;
58346d64076SWei Fang 
58446d64076SWei Fang 	dsa_switch_for_each_available_port(dp, priv->ds)
58546d64076SWei Fang 		bitmap |= BIT(dp->index);
58646d64076SWei Fang 
58746d64076SWei Fang 	return bitmap;
58846d64076SWei Fang }
58946d64076SWei Fang 
59046d64076SWei Fang static int netc_add_standalone_vlan_entry(struct netc_switch *priv)
59146d64076SWei Fang {
59246d64076SWei Fang 	u32 bitmap_stg = VFT_STG_ID(0) | netc_available_port_bitmap(priv);
59346d64076SWei Fang 	struct vft_cfge_data *cfge;
59446d64076SWei Fang 	u16 cfg;
59546d64076SWei Fang 	int err;
59646d64076SWei Fang 
59746d64076SWei Fang 	cfge = kzalloc_obj(*cfge);
59846d64076SWei Fang 	if (!cfge)
59946d64076SWei Fang 		return -ENOMEM;
60046d64076SWei Fang 
60146d64076SWei Fang 	cfge->bitmap_stg = cpu_to_le32(bitmap_stg);
60246d64076SWei Fang 	cfge->et_eid = cpu_to_le32(NTMP_NULL_ENTRY_ID);
60346d64076SWei Fang 	cfge->fid = cpu_to_le16(NETC_STANDALONE_PVID);
60446d64076SWei Fang 
60546d64076SWei Fang 	/* For standalone ports, MAC learning needs to be disabled, so frames
60646d64076SWei Fang 	 * from other user ports will not be forwarded to the standalone ports,
60746d64076SWei Fang 	 * because there are no FDB entries on the standalone ports. Also, the
60846d64076SWei Fang 	 * frames received by the standalone ports cannot be flooded to other
60946d64076SWei Fang 	 * ports, so MAC forwarding option needs to be set to
61046d64076SWei Fang 	 * MFO_NO_MATCH_DISCARD, so the frames will be discarded rather than
61146d64076SWei Fang 	 * flooding to other ports.
61246d64076SWei Fang 	 */
61346d64076SWei Fang 	cfg = FIELD_PREP(VFT_MLO, MLO_DISABLE) |
61446d64076SWei Fang 	      FIELD_PREP(VFT_MFO, MFO_NO_MATCH_DISCARD);
61546d64076SWei Fang 	cfge->cfg = cpu_to_le16(cfg);
61646d64076SWei Fang 
61746d64076SWei Fang 	err = ntmp_vft_add_entry(&priv->ntmp, NETC_STANDALONE_PVID, cfge);
61846d64076SWei Fang 	if (err)
61946d64076SWei Fang 		dev_err(priv->dev,
62046d64076SWei Fang 			"Failed to add standalone VLAN entry\n");
62146d64076SWei Fang 
62246d64076SWei Fang 	kfree(cfge);
62346d64076SWei Fang 
62446d64076SWei Fang 	return err;
62546d64076SWei Fang }
62646d64076SWei Fang 
62746d64076SWei Fang static int netc_port_add_fdb_entry(struct netc_port *np,
62846d64076SWei Fang 				   const unsigned char *addr, u16 vid)
62946d64076SWei Fang {
63046d64076SWei Fang 	struct netc_switch *priv = np->switch_priv;
63146d64076SWei Fang 	struct netc_fdb_entry *entry;
63246d64076SWei Fang 	struct fdbt_keye_data *keye;
63346d64076SWei Fang 	struct fdbt_cfge_data *cfge;
63446d64076SWei Fang 	int port = np->dp->index;
63546d64076SWei Fang 	u32 cfg = 0;
63646d64076SWei Fang 	int err;
63746d64076SWei Fang 
63846d64076SWei Fang 	entry = kzalloc_obj(*entry);
63946d64076SWei Fang 	if (!entry)
64046d64076SWei Fang 		return -ENOMEM;
64146d64076SWei Fang 
64246d64076SWei Fang 	keye = &entry->keye;
64346d64076SWei Fang 	cfge = &entry->cfge;
64446d64076SWei Fang 	ether_addr_copy(keye->mac_addr, addr);
64546d64076SWei Fang 	keye->fid = cpu_to_le16(vid);
64646d64076SWei Fang 
64746d64076SWei Fang 	cfge->port_bitmap = cpu_to_le32(BIT(port));
64846d64076SWei Fang 	cfge->cfg = cpu_to_le32(cfg);
64946d64076SWei Fang 	cfge->et_eid = cpu_to_le32(NTMP_NULL_ENTRY_ID);
65046d64076SWei Fang 
65146d64076SWei Fang 	err = ntmp_fdbt_add_entry(&priv->ntmp, &entry->entry_id, keye, cfge);
65246d64076SWei Fang 	if (err) {
65346d64076SWei Fang 		kfree(entry);
65446d64076SWei Fang 
65546d64076SWei Fang 		return err;
65646d64076SWei Fang 	}
65746d64076SWei Fang 
65846d64076SWei Fang 	netc_add_fdb_entry(priv, entry);
65946d64076SWei Fang 
66046d64076SWei Fang 	return 0;
66146d64076SWei Fang }
66246d64076SWei Fang 
66346d64076SWei Fang static int netc_port_set_fdb_entry(struct netc_port *np,
66446d64076SWei Fang 				   const unsigned char *addr, u16 vid)
66546d64076SWei Fang {
66646d64076SWei Fang 	struct netc_switch *priv = np->switch_priv;
66746d64076SWei Fang 	struct netc_fdb_entry *entry;
66846d64076SWei Fang 	struct fdbt_cfge_data *cfge;
66946d64076SWei Fang 	int port = np->dp->index;
67046d64076SWei Fang 	__le32 old_port_bitmap;
67146d64076SWei Fang 	int err = 0;
67246d64076SWei Fang 
67346d64076SWei Fang 	mutex_lock(&priv->fdbt_lock);
67446d64076SWei Fang 
67546d64076SWei Fang 	entry = netc_lookup_fdb_entry(priv, addr, vid);
67646d64076SWei Fang 	if (!entry) {
67746d64076SWei Fang 		err = netc_port_add_fdb_entry(np, addr, vid);
67846d64076SWei Fang 		if (err)
67946d64076SWei Fang 			dev_err(priv->dev,
68046d64076SWei Fang 				"Failed to add FDB entry on port %d\n",
68146d64076SWei Fang 				port);
68246d64076SWei Fang 
68346d64076SWei Fang 		goto unlock_fdbt;
68446d64076SWei Fang 	}
68546d64076SWei Fang 
68646d64076SWei Fang 	cfge = &entry->cfge;
68746d64076SWei Fang 	/* If the entry already exists on the port, return 0 directly */
68846d64076SWei Fang 	if (unlikely(cfge->port_bitmap & cpu_to_le32(BIT(port))))
68946d64076SWei Fang 		goto unlock_fdbt;
69046d64076SWei Fang 
69146d64076SWei Fang 	/* If the entry already exists, but not on this port, we need to
69246d64076SWei Fang 	 * update the port bitmap. In general, it should only be valid
69346d64076SWei Fang 	 * for multicast or broadcast address.
69446d64076SWei Fang 	 */
69546d64076SWei Fang 	old_port_bitmap = cfge->port_bitmap;
69646d64076SWei Fang 	if (is_multicast_ether_addr(addr))
69746d64076SWei Fang 		cfge->port_bitmap |= cpu_to_le32(BIT(port));
69846d64076SWei Fang 	else
69946d64076SWei Fang 		cfge->port_bitmap = cpu_to_le32(BIT(port));
70046d64076SWei Fang 
70146d64076SWei Fang 	err = ntmp_fdbt_update_entry(&priv->ntmp, entry->entry_id, cfge);
70246d64076SWei Fang 	if (err) {
70346d64076SWei Fang 		cfge->port_bitmap = old_port_bitmap;
70446d64076SWei Fang 		dev_err(priv->dev, "Failed to set FDB entry on port %d\n",
70546d64076SWei Fang 			port);
70646d64076SWei Fang 	}
70746d64076SWei Fang 
70846d64076SWei Fang unlock_fdbt:
70946d64076SWei Fang 	mutex_unlock(&priv->fdbt_lock);
71046d64076SWei Fang 
71146d64076SWei Fang 	return err;
71246d64076SWei Fang }
71346d64076SWei Fang 
71446d64076SWei Fang static int netc_port_del_fdb_entry(struct netc_port *np,
71546d64076SWei Fang 				   const unsigned char *addr, u16 vid)
71646d64076SWei Fang {
71746d64076SWei Fang 	struct netc_switch *priv = np->switch_priv;
71846d64076SWei Fang 	struct ntmp_user *ntmp = &priv->ntmp;
71946d64076SWei Fang 	struct netc_fdb_entry *entry;
72046d64076SWei Fang 	struct fdbt_cfge_data *cfge;
72146d64076SWei Fang 	int port = np->dp->index;
72246d64076SWei Fang 	int err = 0;
72346d64076SWei Fang 
72446d64076SWei Fang 	mutex_lock(&priv->fdbt_lock);
72546d64076SWei Fang 
72646d64076SWei Fang 	entry = netc_lookup_fdb_entry(priv, addr, vid);
72746d64076SWei Fang 	if (unlikely(!entry))
728751aa5a5SWei Fang 		/* The hardware-learned dynamic FDB entries cannot be deleted
729751aa5a5SWei Fang 		 * through .port_fdb_del() interface.
730751aa5a5SWei Fang 		 * For NTF_MASTER path: Since hardware-learned dynamic FDB
731751aa5a5SWei Fang 		 * entries are never synchronized back to the bridge software
732751aa5a5SWei Fang 		 * database. br_fdb_delete() -> br_fdb_find() cannot find the
733751aa5a5SWei Fang 		 * FDB entry, so .port_fdb_del() will not be called.
734751aa5a5SWei Fang 		 * For NTF_SELF path: dsa_user_netdev_ops does not implement
735751aa5a5SWei Fang 		 * ndo_fdb_del(), so rtnl_fdb_del() falls back to
736751aa5a5SWei Fang 		 * ndo_dflt_fdb_del(), which only supports NUD_PERMANENT static
737751aa5a5SWei Fang 		 * entries and rejects all others with -EINVAL.
73846d64076SWei Fang 		 */
73946d64076SWei Fang 		goto unlock_fdbt;
74046d64076SWei Fang 
74146d64076SWei Fang 	cfge = &entry->cfge;
74246d64076SWei Fang 	if (unlikely(!(cfge->port_bitmap & cpu_to_le32(BIT(port)))))
74346d64076SWei Fang 		goto unlock_fdbt;
74446d64076SWei Fang 
74546d64076SWei Fang 	if (cfge->port_bitmap != cpu_to_le32(BIT(port))) {
74646d64076SWei Fang 		/* If the entry also exists on other ports, we need to
74746d64076SWei Fang 		 * update the entry in the FDB table.
74846d64076SWei Fang 		 */
74946d64076SWei Fang 		cfge->port_bitmap &= cpu_to_le32(~BIT(port));
75046d64076SWei Fang 		err = ntmp_fdbt_update_entry(ntmp, entry->entry_id, cfge);
75146d64076SWei Fang 		if (err) {
75246d64076SWei Fang 			cfge->port_bitmap |= cpu_to_le32(BIT(port));
75346d64076SWei Fang 			goto unlock_fdbt;
75446d64076SWei Fang 		}
75546d64076SWei Fang 	} else {
75646d64076SWei Fang 		/* If the entry only exists on this port, just delete
75746d64076SWei Fang 		 * it from the FDB table.
75846d64076SWei Fang 		 */
75946d64076SWei Fang 		err = ntmp_fdbt_delete_entry(ntmp, entry->entry_id);
76046d64076SWei Fang 		if (err)
76146d64076SWei Fang 			goto unlock_fdbt;
76246d64076SWei Fang 
76346d64076SWei Fang 		netc_del_fdb_entry(entry);
76446d64076SWei Fang 	}
76546d64076SWei Fang 
76646d64076SWei Fang unlock_fdbt:
76746d64076SWei Fang 	mutex_unlock(&priv->fdbt_lock);
76846d64076SWei Fang 
76946d64076SWei Fang 	return err;
77046d64076SWei Fang }
77146d64076SWei Fang 
77246d64076SWei Fang static int netc_add_standalone_fdb_bcast_entry(struct netc_switch *priv)
77346d64076SWei Fang {
77446d64076SWei Fang 	const u8 bcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
77546d64076SWei Fang 	struct dsa_port *dp, *cpu_dp = NULL;
77646d64076SWei Fang 
77746d64076SWei Fang 	dsa_switch_for_each_cpu_port(dp, priv->ds) {
77846d64076SWei Fang 		/* The switch has only one CPU port, so only need to find
77946d64076SWei Fang 		 * the first CPU port to break out of the loop.
78046d64076SWei Fang 		 */
78146d64076SWei Fang 		cpu_dp = dp;
78246d64076SWei Fang 		break;
78346d64076SWei Fang 	}
78446d64076SWei Fang 
78546d64076SWei Fang 	if (!cpu_dp)
78646d64076SWei Fang 		return -ENODEV;
78746d64076SWei Fang 
78846d64076SWei Fang 	/* If the user port acts as a standalone port, then its PVID is 0,
78946d64076SWei Fang 	 * MLO is set to "disable MAC learning" and MFO is set to "discard
79046d64076SWei Fang 	 * frames if no matching entry found in FDB table". Therefore, we
79146d64076SWei Fang 	 * need to add a broadcast FDB entry on the CPU port so that the
79246d64076SWei Fang 	 * broadcast frames received on the user port can be forwarded to
79346d64076SWei Fang 	 * the CPU port.
79446d64076SWei Fang 	 */
79546d64076SWei Fang 	return netc_port_set_fdb_entry(NETC_PORT(priv->ds, cpu_dp->index),
79646d64076SWei Fang 				       bcast, NETC_STANDALONE_PVID);
79746d64076SWei Fang }
79846d64076SWei Fang 
799a5ccb7f5SWei Fang static void netc_port_set_pbpmcr(struct netc_port *np, u64 mapping)
800a5ccb7f5SWei Fang {
801a5ccb7f5SWei Fang 	u32 pbpmcr0 = lower_32_bits(mapping);
802a5ccb7f5SWei Fang 	u32 pbpmcr1 = upper_32_bits(mapping);
803a5ccb7f5SWei Fang 
804a5ccb7f5SWei Fang 	netc_port_wr(np, NETC_PBPMCR0, pbpmcr0);
805a5ccb7f5SWei Fang 	netc_port_wr(np, NETC_PBPMCR1, pbpmcr1);
806a5ccb7f5SWei Fang }
807a5ccb7f5SWei Fang 
808a5ccb7f5SWei Fang static void netc_ipv_to_buffer_pool_mapping(struct netc_switch *priv)
809a5ccb7f5SWei Fang {
810a5ccb7f5SWei Fang 	int bp_per_port = priv->num_bp / priv->info->num_ports;
811a5ccb7f5SWei Fang 	int q = NETC_IPV_NUM / bp_per_port;
812a5ccb7f5SWei Fang 	int r = NETC_IPV_NUM % bp_per_port;
813a5ccb7f5SWei Fang 	int num = q + r;
814a5ccb7f5SWei Fang 
815a5ccb7f5SWei Fang 	/* IPV-to-buffer-pool mapping per port:
816a5ccb7f5SWei Fang 	 * Each port is allocated 'bp_per_port' buffer pools and supports 8
817a5ccb7f5SWei Fang 	 * IPVs, where a higher IPV indicates a higher frame priority. Each
818a5ccb7f5SWei Fang 	 * IPV can be mapped to only one buffer pool, from hardware design
819a5ccb7f5SWei Fang 	 * perspective, bp_per_port will not be greater than 8. So 'q' will
820a5ccb7f5SWei Fang 	 * not be 0.
821a5ccb7f5SWei Fang 	 *
822a5ccb7f5SWei Fang 	 * The mapping rule is as follows:
823a5ccb7f5SWei Fang 	 * - The first 'num' IPVs share the port's first buffer pool (index
824a5ccb7f5SWei Fang 	 * 'base_id').
825a5ccb7f5SWei Fang 	 * - After that, every 'q' IPVs share one buffer pool, with pool
826a5ccb7f5SWei Fang 	 * indices increasing sequentially.
827a5ccb7f5SWei Fang 	 */
828a5ccb7f5SWei Fang 	for (int i = 0; i < priv->info->num_ports; i++) {
829a5ccb7f5SWei Fang 		u32 base_id = i * bp_per_port;
830a5ccb7f5SWei Fang 		u32 bp_id = base_id;
831a5ccb7f5SWei Fang 		u64 mapping = 0;
832a5ccb7f5SWei Fang 
833a5ccb7f5SWei Fang 		for (int ipv = 0; ipv < NETC_IPV_NUM; ipv++) {
834a5ccb7f5SWei Fang 			/* Update the buffer pool index */
835a5ccb7f5SWei Fang 			if (ipv >= num)
836a5ccb7f5SWei Fang 				bp_id = base_id + ((ipv - num) / q) + 1;
837a5ccb7f5SWei Fang 
838a5ccb7f5SWei Fang 			mapping |= (u64)bp_id << (ipv * 8);
839a5ccb7f5SWei Fang 		}
840a5ccb7f5SWei Fang 
841a5ccb7f5SWei Fang 		netc_port_set_pbpmcr(priv->ports[i], mapping);
842a5ccb7f5SWei Fang 	}
843a5ccb7f5SWei Fang }
844a5ccb7f5SWei Fang 
845a5ccb7f5SWei Fang static int netc_switch_bpt_default_config(struct netc_switch *priv)
846a5ccb7f5SWei Fang {
847a5ccb7f5SWei Fang 	if (priv->num_bp < priv->info->num_ports)
848a5ccb7f5SWei Fang 		return -EINVAL;
849a5ccb7f5SWei Fang 
850a5ccb7f5SWei Fang 	priv->bpt_list = devm_kcalloc(priv->dev, priv->num_bp,
851a5ccb7f5SWei Fang 				      sizeof(struct bpt_cfge_data),
852a5ccb7f5SWei Fang 				      GFP_KERNEL);
853a5ccb7f5SWei Fang 	if (!priv->bpt_list)
854a5ccb7f5SWei Fang 		return -ENOMEM;
855a5ccb7f5SWei Fang 
856a5ccb7f5SWei Fang 	/* Initialize the maximum threshold of each buffer pool entry */
857a5ccb7f5SWei Fang 	for (int i = 0; i < priv->num_bp; i++) {
858a5ccb7f5SWei Fang 		struct bpt_cfge_data *cfge = &priv->bpt_list[i];
859a5ccb7f5SWei Fang 		int err;
860a5ccb7f5SWei Fang 
861a5ccb7f5SWei Fang 		cfge->max_thresh = cpu_to_le16(NETC_BP_THRESH);
862a5ccb7f5SWei Fang 		err = ntmp_bpt_update_entry(&priv->ntmp, i, cfge);
863a5ccb7f5SWei Fang 		if (err)
864a5ccb7f5SWei Fang 			return err;
865a5ccb7f5SWei Fang 	}
866a5ccb7f5SWei Fang 
867a5ccb7f5SWei Fang 	netc_ipv_to_buffer_pool_mapping(priv);
868a5ccb7f5SWei Fang 
869a5ccb7f5SWei Fang 	return 0;
870a5ccb7f5SWei Fang }
871a5ccb7f5SWei Fang 
872187fbae0SWei Fang static int netc_setup(struct dsa_switch *ds)
873187fbae0SWei Fang {
874187fbae0SWei Fang 	struct netc_switch *priv = ds->priv;
875187fbae0SWei Fang 	struct dsa_port *dp;
876187fbae0SWei Fang 	int err;
877187fbae0SWei Fang 
878187fbae0SWei Fang 	err = netc_init_switch_id(priv);
879187fbae0SWei Fang 	if (err)
880187fbae0SWei Fang 		return err;
881187fbae0SWei Fang 
88246d64076SWei Fang 	netc_get_switch_capabilities(priv);
88346d64076SWei Fang 
884187fbae0SWei Fang 	err = netc_init_all_ports(priv);
885187fbae0SWei Fang 	if (err)
886187fbae0SWei Fang 		return err;
887187fbae0SWei Fang 
888187fbae0SWei Fang 	err = netc_init_ntmp_user(priv);
889187fbae0SWei Fang 	if (err)
890187fbae0SWei Fang 		return err;
891187fbae0SWei Fang 
89246d64076SWei Fang 	INIT_HLIST_HEAD(&priv->fdb_list);
89346d64076SWei Fang 	mutex_init(&priv->fdbt_lock);
894*05b5ee61SWei Fang 	priv->fdbt_ageing_delay = NETC_FDBT_AGEING_DELAY;
895*05b5ee61SWei Fang 	atomic_set(&priv->br_cnt, 0);
896*05b5ee61SWei Fang 	INIT_DELAYED_WORK(&priv->fdbt_ageing_work,
897*05b5ee61SWei Fang 			  netc_clean_fdbt_ageing_entries);
89884b4a3b3SWei Fang 	INIT_HLIST_HEAD(&priv->vlan_list);
89984b4a3b3SWei Fang 	mutex_init(&priv->vft_lock);
90046d64076SWei Fang 
901187fbae0SWei Fang 	netc_switch_fixed_config(priv);
902187fbae0SWei Fang 
903187fbae0SWei Fang 	/* default setting for ports */
904187fbae0SWei Fang 	dsa_switch_for_each_available_port(dp, ds)
905187fbae0SWei Fang 		netc_port_default_config(priv->ports[dp->index]);
906187fbae0SWei Fang 
907a5ccb7f5SWei Fang 	err = netc_switch_bpt_default_config(priv);
908a5ccb7f5SWei Fang 	if (err)
909a5ccb7f5SWei Fang 		goto free_lock_and_ntmp_user;
910a5ccb7f5SWei Fang 
91146d64076SWei Fang 	err = netc_add_standalone_vlan_entry(priv);
91246d64076SWei Fang 	if (err)
91346d64076SWei Fang 		goto free_lock_and_ntmp_user;
91446d64076SWei Fang 
91546d64076SWei Fang 	err = netc_add_standalone_fdb_bcast_entry(priv);
91646d64076SWei Fang 	if (err)
91746d64076SWei Fang 		goto free_lock_and_ntmp_user;
91846d64076SWei Fang 
919187fbae0SWei Fang 	return 0;
92046d64076SWei Fang 
92146d64076SWei Fang free_lock_and_ntmp_user:
92246d64076SWei Fang 	/* No need to clear the hardware state, netc_setup() is only called
92346d64076SWei Fang 	 * when the driver is bound, and FLR will be performed to reset the
92446d64076SWei Fang 	 * hardware state.
92546d64076SWei Fang 	 */
92646d64076SWei Fang 	mutex_destroy(&priv->fdbt_lock);
92784b4a3b3SWei Fang 	mutex_destroy(&priv->vft_lock);
92846d64076SWei Fang 	netc_free_ntmp_user(priv);
92946d64076SWei Fang 
93046d64076SWei Fang 	return err;
93146d64076SWei Fang }
93246d64076SWei Fang 
93346d64076SWei Fang static void netc_destroy_all_lists(struct netc_switch *priv)
93446d64076SWei Fang {
93546d64076SWei Fang 	netc_destroy_fdb_list(priv);
93646d64076SWei Fang 	mutex_destroy(&priv->fdbt_lock);
93784b4a3b3SWei Fang 	netc_destroy_vlan_list(priv);
93884b4a3b3SWei Fang 	mutex_destroy(&priv->vft_lock);
93946d64076SWei Fang }
94046d64076SWei Fang 
94146d64076SWei Fang static void netc_free_host_flood_rules(struct netc_switch *priv)
94246d64076SWei Fang {
94346d64076SWei Fang 	struct dsa_port *dp;
94446d64076SWei Fang 
94546d64076SWei Fang 	dsa_switch_for_each_user_port(dp, priv->ds) {
94646d64076SWei Fang 		struct netc_port *np = priv->ports[dp->index];
94746d64076SWei Fang 
94846d64076SWei Fang 		/* No need to clear the hardware IPFT entry. Because PCIe
94946d64076SWei Fang 		 * FLR will be performed when the switch is re-registered,
95046d64076SWei Fang 		 * it will reset hardware state. So only need to free the
95146d64076SWei Fang 		 * memory to avoid memory leak.
95246d64076SWei Fang 		 */
95346d64076SWei Fang 		kfree(np->host_flood);
95446d64076SWei Fang 		np->host_flood = NULL;
95546d64076SWei Fang 	}
956187fbae0SWei Fang }
957187fbae0SWei Fang 
958187fbae0SWei Fang static void netc_teardown(struct dsa_switch *ds)
959187fbae0SWei Fang {
960187fbae0SWei Fang 	struct netc_switch *priv = ds->priv;
961187fbae0SWei Fang 
962*05b5ee61SWei Fang 	disable_delayed_work_sync(&priv->fdbt_ageing_work);
96346d64076SWei Fang 	netc_destroy_all_lists(priv);
96446d64076SWei Fang 	netc_free_host_flood_rules(priv);
965187fbae0SWei Fang 	netc_free_ntmp_user(priv);
966187fbae0SWei Fang }
967187fbae0SWei Fang 
968187fbae0SWei Fang static bool netc_port_is_emdio_consumer(struct device_node *node)
969187fbae0SWei Fang {
970187fbae0SWei Fang 	struct device_node *mdio_node;
971187fbae0SWei Fang 
972187fbae0SWei Fang 	/* If the port node has phy-handle property and it does
973187fbae0SWei Fang 	 * not contain a mdio child node, then the port is the
974187fbae0SWei Fang 	 * EMDIO consumer.
975187fbae0SWei Fang 	 */
976187fbae0SWei Fang 	mdio_node = of_get_child_by_name(node, "mdio");
977187fbae0SWei Fang 	if (!mdio_node)
978187fbae0SWei Fang 		return true;
979187fbae0SWei Fang 
980187fbae0SWei Fang 	of_node_put(mdio_node);
981187fbae0SWei Fang 
982187fbae0SWei Fang 	return false;
983187fbae0SWei Fang }
984187fbae0SWei Fang 
985187fbae0SWei Fang /* Currently, phylink_of_phy_connect() is called by dsa_user_create(),
986187fbae0SWei Fang  * so if the switch uses the external MDIO controller (like the EMDIO
987187fbae0SWei Fang  * function) to manage the external PHYs. The MDIO bus may not be
988187fbae0SWei Fang  * created when phylink_of_phy_connect() is called, so it will return
989187fbae0SWei Fang  * an error and cause the switch driver to fail to probe.
990187fbae0SWei Fang  * This workaround can be removed when DSA phylink_of_phy_connect()
991187fbae0SWei Fang  * calls are moved from probe() to ndo_open().
992187fbae0SWei Fang  */
993187fbae0SWei Fang static int netc_switch_check_emdio_is_ready(struct device *dev)
994187fbae0SWei Fang {
995187fbae0SWei Fang 	struct device_node *ports, *phy_node;
996187fbae0SWei Fang 	struct phy_device *phydev;
997187fbae0SWei Fang 	int err = 0;
998187fbae0SWei Fang 
999187fbae0SWei Fang 	ports = of_get_child_by_name(dev->of_node, "ethernet-ports");
1000187fbae0SWei Fang 	if (!ports) {
1001187fbae0SWei Fang 		dev_err(dev, "Cannot find the ethernet-ports node\n");
1002187fbae0SWei Fang 		return -EINVAL;
1003187fbae0SWei Fang 	}
1004187fbae0SWei Fang 
1005187fbae0SWei Fang 	for_each_available_child_of_node_scoped(ports, child) {
1006187fbae0SWei Fang 		/* If the node does not have phy-handle property, then the
1007187fbae0SWei Fang 		 * port does not connect to a PHY, so the port is not the
1008187fbae0SWei Fang 		 * EMDIO consumer.
1009187fbae0SWei Fang 		 */
1010187fbae0SWei Fang 		phy_node = of_parse_phandle(child, "phy-handle", 0);
1011187fbae0SWei Fang 		if (!phy_node)
1012187fbae0SWei Fang 			continue;
1013187fbae0SWei Fang 
1014187fbae0SWei Fang 		/* Note that from the hardware perspective, the switch ports
1015187fbae0SWei Fang 		 * do not support sharing the MDIO bus defined under one port.
1016187fbae0SWei Fang 		 * Each port can only access its own external PHY through its
1017187fbae0SWei Fang 		 * port MDIO bus.
1018187fbae0SWei Fang 		 */
1019187fbae0SWei Fang 		if (!netc_port_is_emdio_consumer(child)) {
1020187fbae0SWei Fang 			of_node_put(phy_node);
1021187fbae0SWei Fang 			continue;
1022187fbae0SWei Fang 		}
1023187fbae0SWei Fang 
1024187fbae0SWei Fang 		phydev = of_phy_find_device(phy_node);
1025187fbae0SWei Fang 		of_node_put(phy_node);
1026187fbae0SWei Fang 		if (!phydev) {
1027187fbae0SWei Fang 			err = -EPROBE_DEFER;
1028187fbae0SWei Fang 			goto out;
1029187fbae0SWei Fang 		}
1030187fbae0SWei Fang 
1031187fbae0SWei Fang 		put_device(&phydev->mdio.dev);
1032187fbae0SWei Fang 	}
1033187fbae0SWei Fang 
1034187fbae0SWei Fang out:
1035187fbae0SWei Fang 	of_node_put(ports);
1036187fbae0SWei Fang 
1037187fbae0SWei Fang 	return err;
1038187fbae0SWei Fang }
1039187fbae0SWei Fang 
1040187fbae0SWei Fang static int netc_switch_pci_init(struct pci_dev *pdev)
1041187fbae0SWei Fang {
1042187fbae0SWei Fang 	struct device *dev = &pdev->dev;
1043187fbae0SWei Fang 	struct netc_switch_regs *regs;
1044187fbae0SWei Fang 	struct netc_switch *priv;
1045187fbae0SWei Fang 	void __iomem *base;
1046187fbae0SWei Fang 	int err;
1047187fbae0SWei Fang 
1048187fbae0SWei Fang 	pcie_flr(pdev);
1049187fbae0SWei Fang 	err = pcim_enable_device(pdev);
1050187fbae0SWei Fang 	if (err)
1051187fbae0SWei Fang 		return dev_err_probe(dev, err, "Failed to enable device\n");
1052187fbae0SWei Fang 
1053187fbae0SWei Fang 	err = pcim_request_all_regions(pdev, KBUILD_MODNAME);
1054187fbae0SWei Fang 	if (err)
1055187fbae0SWei Fang 		return dev_err_probe(dev, err, "Failed to request regions\n");
1056187fbae0SWei Fang 
1057187fbae0SWei Fang 	/* The command BD rings and NTMP tables need DMA. No need to check
1058187fbae0SWei Fang 	 * the return value, because it never returns fail when the mask is
1059187fbae0SWei Fang 	 * DMA_BIT_MASK(64), see dma-api-howto.rst.
1060187fbae0SWei Fang 	 */
1061187fbae0SWei Fang 	dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
1062187fbae0SWei Fang 
1063187fbae0SWei Fang 	if (pci_resource_len(pdev, NETC_REGS_BAR) < NETC_REGS_SIZE) {
1064187fbae0SWei Fang 		return dev_err_probe(dev, -EINVAL,
1065187fbae0SWei Fang 				     "Invalid register space size\n");
1066187fbae0SWei Fang 	}
1067187fbae0SWei Fang 
1068187fbae0SWei Fang 	base = pcim_iomap(pdev, NETC_REGS_BAR, 0);
1069187fbae0SWei Fang 	if (!base)
1070187fbae0SWei Fang 		return dev_err_probe(dev, -ENXIO, "pcim_iomap() failed\n");
1071187fbae0SWei Fang 
1072187fbae0SWei Fang 	pci_set_master(pdev);
1073187fbae0SWei Fang 
1074187fbae0SWei Fang 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
1075187fbae0SWei Fang 	if (!priv)
1076187fbae0SWei Fang 		return -ENOMEM;
1077187fbae0SWei Fang 
1078187fbae0SWei Fang 	priv->pdev = pdev;
1079187fbae0SWei Fang 	priv->dev = dev;
1080187fbae0SWei Fang 
1081187fbae0SWei Fang 	regs = &priv->regs;
1082187fbae0SWei Fang 	regs->base = base;
1083187fbae0SWei Fang 	regs->port = regs->base + NETC_REGS_PORT_BASE;
1084187fbae0SWei Fang 	regs->global = regs->base + NETC_REGS_GLOBAL_BASE;
1085187fbae0SWei Fang 	pci_set_drvdata(pdev, priv);
1086187fbae0SWei Fang 
1087187fbae0SWei Fang 	return 0;
1088187fbae0SWei Fang }
1089187fbae0SWei Fang 
1090187fbae0SWei Fang static void netc_switch_get_ip_revision(struct netc_switch *priv)
1091187fbae0SWei Fang {
1092187fbae0SWei Fang 	struct netc_switch_regs *regs = &priv->regs;
1093187fbae0SWei Fang 	u32 val = netc_glb_rd(regs, NETC_IPBRR0);
1094187fbae0SWei Fang 
1095187fbae0SWei Fang 	priv->revision = FIELD_GET(IPBRR0_IP_REV, val);
1096187fbae0SWei Fang }
1097187fbae0SWei Fang 
109884b4a3b3SWei Fang static void netc_init_ett_cfge(struct ett_cfge_data *cfge,
109984b4a3b3SWei Fang 			       bool untagged, u32 ect_eid)
110084b4a3b3SWei Fang {
110184b4a3b3SWei Fang 	u32 vuda_sqta = FMTEID_VUDA_SQTA;
110284b4a3b3SWei Fang 	u16 efm_cfg = 0;
110384b4a3b3SWei Fang 
110484b4a3b3SWei Fang 	if (ect_eid != NTMP_NULL_ENTRY_ID) {
110584b4a3b3SWei Fang 		/* Increase egress frame counter */
110684b4a3b3SWei Fang 		efm_cfg |= FIELD_PREP(ETT_ECA, ETT_ECA_INC);
110784b4a3b3SWei Fang 		cfge->ec_eid = cpu_to_le32(ect_eid);
110884b4a3b3SWei Fang 	}
110984b4a3b3SWei Fang 
111084b4a3b3SWei Fang 	/* If egress rule is VLAN untagged */
111184b4a3b3SWei Fang 	if (untagged) {
111284b4a3b3SWei Fang 		/* delete outer VLAN tag */
111384b4a3b3SWei Fang 		vuda_sqta |= FIELD_PREP(FMTEID_VUDA, FMTEID_VUDA_DEL_OTAG);
111484b4a3b3SWei Fang 		/* length change: twos-complement notation */
111584b4a3b3SWei Fang 		efm_cfg |= FIELD_PREP(ETT_EFM_LEN_CHANGE,
111684b4a3b3SWei Fang 				      ETT_FRM_LEN_DEL_VLAN);
111784b4a3b3SWei Fang 	}
111884b4a3b3SWei Fang 
111984b4a3b3SWei Fang 	cfge->efm_eid = cpu_to_le32(vuda_sqta);
112084b4a3b3SWei Fang 	cfge->efm_cfg = cpu_to_le16(efm_cfg);
112184b4a3b3SWei Fang }
112284b4a3b3SWei Fang 
112384b4a3b3SWei Fang static int netc_add_ett_entry(struct netc_switch *priv, bool untagged,
112484b4a3b3SWei Fang 			      u32 ett_eid, u32 ect_eid)
112584b4a3b3SWei Fang {
112684b4a3b3SWei Fang 	struct ntmp_user *ntmp = &priv->ntmp;
112784b4a3b3SWei Fang 	struct ett_cfge_data cfge = {};
112884b4a3b3SWei Fang 
112984b4a3b3SWei Fang 	netc_init_ett_cfge(&cfge, untagged, ect_eid);
113084b4a3b3SWei Fang 
113184b4a3b3SWei Fang 	return ntmp_ett_add_entry(ntmp, ett_eid, &cfge);
113284b4a3b3SWei Fang }
113384b4a3b3SWei Fang 
113484b4a3b3SWei Fang static int netc_update_ett_entry(struct netc_switch *priv, bool untagged,
113584b4a3b3SWei Fang 				 u32 ett_eid, u32 ect_eid)
113684b4a3b3SWei Fang {
113784b4a3b3SWei Fang 	struct ntmp_user *ntmp = &priv->ntmp;
113884b4a3b3SWei Fang 	struct ett_cfge_data cfge = {};
113984b4a3b3SWei Fang 
114084b4a3b3SWei Fang 	netc_init_ett_cfge(&cfge, untagged, ect_eid);
114184b4a3b3SWei Fang 
114284b4a3b3SWei Fang 	return ntmp_ett_update_entry(ntmp, ett_eid, &cfge);
114384b4a3b3SWei Fang }
114484b4a3b3SWei Fang 
114584b4a3b3SWei Fang static int netc_add_ett_group_entries(struct netc_switch *priv,
114684b4a3b3SWei Fang 				      u32 untagged_port_bitmap,
114784b4a3b3SWei Fang 				      u32 ett_base_eid,
114884b4a3b3SWei Fang 				      u32 ect_base_eid)
114984b4a3b3SWei Fang {
115084b4a3b3SWei Fang 	struct netc_port **ports = priv->ports;
115184b4a3b3SWei Fang 	u32 ett_eid, ect_eid;
115284b4a3b3SWei Fang 	bool untagged;
115384b4a3b3SWei Fang 	int i, err;
115484b4a3b3SWei Fang 
115584b4a3b3SWei Fang 	for (i = 0; i < priv->info->num_ports; i++) {
115684b4a3b3SWei Fang 		if (!ports[i]->dp)
115784b4a3b3SWei Fang 			continue;
115884b4a3b3SWei Fang 
115984b4a3b3SWei Fang 		untagged = !!(untagged_port_bitmap & BIT(i));
116084b4a3b3SWei Fang 		ett_eid = ett_base_eid + ports[i]->ett_offset;
116184b4a3b3SWei Fang 		ect_eid = NTMP_NULL_ENTRY_ID;
116284b4a3b3SWei Fang 		if (ect_base_eid != NTMP_NULL_ENTRY_ID)
116384b4a3b3SWei Fang 			ect_eid = ect_base_eid + ports[i]->ett_offset;
116484b4a3b3SWei Fang 
116584b4a3b3SWei Fang 		err = netc_add_ett_entry(priv, untagged, ett_eid, ect_eid);
116684b4a3b3SWei Fang 		if (err)
116784b4a3b3SWei Fang 			goto clear_ett_entries;
116884b4a3b3SWei Fang 	}
116984b4a3b3SWei Fang 
117084b4a3b3SWei Fang 	return 0;
117184b4a3b3SWei Fang 
117284b4a3b3SWei Fang clear_ett_entries:
117384b4a3b3SWei Fang 	while (--i >= 0) {
117484b4a3b3SWei Fang 		if (!ports[i]->dp)
117584b4a3b3SWei Fang 			continue;
117684b4a3b3SWei Fang 
117784b4a3b3SWei Fang 		ett_eid = ett_base_eid + ports[i]->ett_offset;
117884b4a3b3SWei Fang 		ntmp_ett_delete_entry(&priv->ntmp, ett_eid);
117984b4a3b3SWei Fang 	}
118084b4a3b3SWei Fang 
118184b4a3b3SWei Fang 	return err;
118284b4a3b3SWei Fang }
118384b4a3b3SWei Fang 
118484b4a3b3SWei Fang static int netc_add_vlan_egress_rule(struct netc_switch *priv,
118584b4a3b3SWei Fang 				     struct netc_vlan_entry *entry)
118684b4a3b3SWei Fang {
118784b4a3b3SWei Fang 	u32 num_ports = netc_num_available_ports(priv);
118884b4a3b3SWei Fang 	struct ntmp_user *ntmp = &priv->ntmp;
118984b4a3b3SWei Fang 	u32 ect_eid = NTMP_NULL_ENTRY_ID;
119084b4a3b3SWei Fang 	u32 ett_eid, ett_gid, ect_gid;
119184b4a3b3SWei Fang 	int err;
119284b4a3b3SWei Fang 
119384b4a3b3SWei Fang 	/* Step 1: Find available egress counter table entries and update
119484b4a3b3SWei Fang 	 * these entries.
119584b4a3b3SWei Fang 	 */
119684b4a3b3SWei Fang 	ect_gid = ntmp_lookup_free_eid(ntmp->ect_gid_bitmap,
119784b4a3b3SWei Fang 				       ntmp->ect_bitmap_size);
119884b4a3b3SWei Fang 	if (ect_gid == NTMP_NULL_ENTRY_ID) {
119984b4a3b3SWei Fang 		dev_info(priv->dev,
120084b4a3b3SWei Fang 			 "No egress counter table entries available\n");
120184b4a3b3SWei Fang 	} else {
120284b4a3b3SWei Fang 		ect_eid = ect_gid * num_ports;
120384b4a3b3SWei Fang 		for (int i = 0; i < num_ports; i++)
120484b4a3b3SWei Fang 			/* There is no need to check the return value, the only
120584b4a3b3SWei Fang 			 * issue is that the entry's counter might be inaccurate,
120684b4a3b3SWei Fang 			 * but it will not affect the functionality, it is only
120784b4a3b3SWei Fang 			 * for future debugging.
120884b4a3b3SWei Fang 			 */
120984b4a3b3SWei Fang 			ntmp_ect_update_entry(ntmp, ect_eid + i);
121084b4a3b3SWei Fang 	}
121184b4a3b3SWei Fang 
121284b4a3b3SWei Fang 	/* Step 2: Find available egress treatment table entries and add
121384b4a3b3SWei Fang 	 * these entries.
121484b4a3b3SWei Fang 	 */
121584b4a3b3SWei Fang 	ett_gid = ntmp_lookup_free_eid(ntmp->ett_gid_bitmap,
121684b4a3b3SWei Fang 				       ntmp->ett_bitmap_size);
121784b4a3b3SWei Fang 	if (ett_gid == NTMP_NULL_ENTRY_ID) {
121884b4a3b3SWei Fang 		dev_err(priv->dev,
121984b4a3b3SWei Fang 			"No egress treatment table entries available\n");
122084b4a3b3SWei Fang 		err = -ENOSPC;
122184b4a3b3SWei Fang 		goto clear_ect_gid;
122284b4a3b3SWei Fang 	}
122384b4a3b3SWei Fang 
122484b4a3b3SWei Fang 	ett_eid = ett_gid * num_ports;
122584b4a3b3SWei Fang 	err = netc_add_ett_group_entries(priv, entry->untagged_port_bitmap,
122684b4a3b3SWei Fang 					 ett_eid, ect_eid);
122784b4a3b3SWei Fang 	if (err)
122884b4a3b3SWei Fang 		goto clear_ett_gid;
122984b4a3b3SWei Fang 
123084b4a3b3SWei Fang 	entry->cfge.et_eid = cpu_to_le32(ett_eid);
123184b4a3b3SWei Fang 	entry->ect_gid = ect_gid;
123284b4a3b3SWei Fang 
123384b4a3b3SWei Fang 	return 0;
123484b4a3b3SWei Fang 
123584b4a3b3SWei Fang clear_ett_gid:
123684b4a3b3SWei Fang 	ntmp_clear_eid_bitmap(ntmp->ett_gid_bitmap, ett_gid);
123784b4a3b3SWei Fang 
123884b4a3b3SWei Fang clear_ect_gid:
123984b4a3b3SWei Fang 	if (ect_gid != NTMP_NULL_ENTRY_ID)
124084b4a3b3SWei Fang 		ntmp_clear_eid_bitmap(ntmp->ect_gid_bitmap, ect_gid);
124184b4a3b3SWei Fang 
124284b4a3b3SWei Fang 	return err;
124384b4a3b3SWei Fang }
124484b4a3b3SWei Fang 
124584b4a3b3SWei Fang static void netc_delete_vlan_egress_rule(struct netc_switch *priv,
124684b4a3b3SWei Fang 					 struct netc_vlan_entry *entry)
124784b4a3b3SWei Fang {
124884b4a3b3SWei Fang 	u32 num_ports = netc_num_available_ports(priv);
124984b4a3b3SWei Fang 	struct ntmp_user *ntmp = &priv->ntmp;
125084b4a3b3SWei Fang 	u32 ett_eid, ett_gid;
125184b4a3b3SWei Fang 
125284b4a3b3SWei Fang 	ett_eid = le32_to_cpu(entry->cfge.et_eid);
125384b4a3b3SWei Fang 	if (ett_eid == NTMP_NULL_ENTRY_ID)
125484b4a3b3SWei Fang 		return;
125584b4a3b3SWei Fang 
125684b4a3b3SWei Fang 	ett_gid = ett_eid / num_ports;
125784b4a3b3SWei Fang 	ntmp_clear_eid_bitmap(ntmp->ett_gid_bitmap, ett_gid);
125884b4a3b3SWei Fang 	for (int i = 0; i < num_ports; i++)
125984b4a3b3SWei Fang 		ntmp_ett_delete_entry(ntmp, ett_eid + i);
126084b4a3b3SWei Fang 
126184b4a3b3SWei Fang 	if (entry->ect_gid == NTMP_NULL_ENTRY_ID)
126284b4a3b3SWei Fang 		return;
126384b4a3b3SWei Fang 
126484b4a3b3SWei Fang 	ntmp_clear_eid_bitmap(ntmp->ect_gid_bitmap, entry->ect_gid);
126584b4a3b3SWei Fang }
126684b4a3b3SWei Fang 
126784b4a3b3SWei Fang static int netc_port_update_vlan_egress_rule(struct netc_port *np,
126884b4a3b3SWei Fang 					     struct netc_vlan_entry *entry)
126984b4a3b3SWei Fang {
127084b4a3b3SWei Fang 	bool untagged = !!(entry->untagged_port_bitmap & BIT(np->dp->index));
127184b4a3b3SWei Fang 	u32 num_ports = netc_num_available_ports(np->switch_priv);
127284b4a3b3SWei Fang 	u32 ett_eid = le32_to_cpu(entry->cfge.et_eid);
127384b4a3b3SWei Fang 	struct netc_switch *priv = np->switch_priv;
127484b4a3b3SWei Fang 	u32 ect_eid = NTMP_NULL_ENTRY_ID;
127584b4a3b3SWei Fang 	int err;
127684b4a3b3SWei Fang 
127784b4a3b3SWei Fang 	if (ett_eid == NTMP_NULL_ENTRY_ID)
127884b4a3b3SWei Fang 		return 0;
127984b4a3b3SWei Fang 
128084b4a3b3SWei Fang 	if (entry->ect_gid != NTMP_NULL_ENTRY_ID)
128184b4a3b3SWei Fang 		/* Each ETT entry maps to an ECT entry if ect_gid is not NULL
128284b4a3b3SWei Fang 		 * entry ID. The offset of the ECT entry corresponding to the
128384b4a3b3SWei Fang 		 * port in the group is equal to ett_offset.
128484b4a3b3SWei Fang 		 */
128584b4a3b3SWei Fang 		ect_eid = entry->ect_gid * num_ports + np->ett_offset;
128684b4a3b3SWei Fang 
128784b4a3b3SWei Fang 	ett_eid += np->ett_offset;
128884b4a3b3SWei Fang 	err = netc_update_ett_entry(priv, untagged, ett_eid, ect_eid);
128984b4a3b3SWei Fang 	if (err) {
129084b4a3b3SWei Fang 		dev_err(priv->dev,
129184b4a3b3SWei Fang 			"Failed to update VLAN %u egress rule on port %d\n",
129284b4a3b3SWei Fang 			entry->vid, np->dp->index);
129384b4a3b3SWei Fang 		return err;
129484b4a3b3SWei Fang 	}
129584b4a3b3SWei Fang 
129684b4a3b3SWei Fang 	if (ect_eid != NTMP_NULL_ENTRY_ID)
129784b4a3b3SWei Fang 		ntmp_ect_update_entry(&priv->ntmp, ect_eid);
129884b4a3b3SWei Fang 
129984b4a3b3SWei Fang 	return 0;
130084b4a3b3SWei Fang }
130184b4a3b3SWei Fang 
130284b4a3b3SWei Fang static int netc_port_add_vlan_entry(struct netc_port *np, u16 vid,
130384b4a3b3SWei Fang 				    bool untagged)
130484b4a3b3SWei Fang {
130584b4a3b3SWei Fang 	struct netc_switch *priv = np->switch_priv;
130684b4a3b3SWei Fang 	struct netc_vlan_entry *entry;
130784b4a3b3SWei Fang 	struct vft_cfge_data *cfge;
130884b4a3b3SWei Fang 	u32 index = np->dp->index;
130984b4a3b3SWei Fang 	u32 bitmap_stg;
131084b4a3b3SWei Fang 	int err;
131184b4a3b3SWei Fang 	u16 cfg;
131284b4a3b3SWei Fang 
131384b4a3b3SWei Fang 	entry = kzalloc_obj(*entry);
131484b4a3b3SWei Fang 	if (!entry)
131584b4a3b3SWei Fang 		return -ENOMEM;
131684b4a3b3SWei Fang 
131784b4a3b3SWei Fang 	entry->vid = vid;
131884b4a3b3SWei Fang 	entry->ect_gid = NTMP_NULL_ENTRY_ID;
131984b4a3b3SWei Fang 
132084b4a3b3SWei Fang 	bitmap_stg = BIT(index) | VFT_STG_ID(0);
1321751aa5a5SWei Fang 	/* If the VID is a VLAN-unaware PVID, the CPU port needs to be
1322751aa5a5SWei Fang 	 * a member of this VLAN.
1323751aa5a5SWei Fang 	 */
1324751aa5a5SWei Fang 	if (dsa_port_is_user(np->dp) &&
1325751aa5a5SWei Fang 	    vid >= NETC_VLAN_UNAWARE_PVID(priv->ds->max_num_bridges)) {
1326751aa5a5SWei Fang 		struct dsa_port *cpu_dp = np->dp->cpu_dp;
1327751aa5a5SWei Fang 
1328751aa5a5SWei Fang 		bitmap_stg |= BIT(cpu_dp->index);
1329751aa5a5SWei Fang 	}
1330751aa5a5SWei Fang 
133184b4a3b3SWei Fang 	cfg = FIELD_PREP(VFT_MLO, MLO_HW) |
133284b4a3b3SWei Fang 	      FIELD_PREP(VFT_MFO, MFO_NO_MATCH_FLOOD);
133384b4a3b3SWei Fang 
133484b4a3b3SWei Fang 	cfge = &entry->cfge;
133584b4a3b3SWei Fang 	cfge->et_eid = cpu_to_le32(NTMP_NULL_ENTRY_ID);
133684b4a3b3SWei Fang 	cfge->bitmap_stg = cpu_to_le32(bitmap_stg);
133784b4a3b3SWei Fang 	cfge->fid = cpu_to_le16(vid);
133884b4a3b3SWei Fang 	cfge->cfg = cpu_to_le16(cfg);
133984b4a3b3SWei Fang 	cfge->eta_port_bitmap = cpu_to_le32(priv->port_bitmap);
134084b4a3b3SWei Fang 
134184b4a3b3SWei Fang 	if (untagged)
134284b4a3b3SWei Fang 		entry->untagged_port_bitmap = BIT(index);
134384b4a3b3SWei Fang 
134484b4a3b3SWei Fang 	err = netc_add_vlan_egress_rule(priv, entry);
134584b4a3b3SWei Fang 	if (err)
134684b4a3b3SWei Fang 		goto free_vlan_entry;
134784b4a3b3SWei Fang 
134884b4a3b3SWei Fang 	err = ntmp_vft_add_entry(&priv->ntmp, vid, cfge);
134984b4a3b3SWei Fang 	if (err) {
135084b4a3b3SWei Fang 		dev_err(priv->dev,
135184b4a3b3SWei Fang 			"Failed to add VLAN %u entry on port %d\n",
135284b4a3b3SWei Fang 			vid, index);
135384b4a3b3SWei Fang 		goto delete_vlan_egress_rule;
135484b4a3b3SWei Fang 	}
135584b4a3b3SWei Fang 
135684b4a3b3SWei Fang 	netc_add_vlan_entry(priv, entry);
135784b4a3b3SWei Fang 
135884b4a3b3SWei Fang 	return 0;
135984b4a3b3SWei Fang 
136084b4a3b3SWei Fang delete_vlan_egress_rule:
136184b4a3b3SWei Fang 	netc_delete_vlan_egress_rule(priv, entry);
136284b4a3b3SWei Fang free_vlan_entry:
136384b4a3b3SWei Fang 	kfree(entry);
136484b4a3b3SWei Fang 
136584b4a3b3SWei Fang 	return err;
136684b4a3b3SWei Fang }
136784b4a3b3SWei Fang 
1368751aa5a5SWei Fang static bool netc_port_vlan_egress_rule_changed(struct netc_switch *priv,
1369751aa5a5SWei Fang 					       struct netc_vlan_entry *entry,
137084b4a3b3SWei Fang 					       int port, bool untagged)
137184b4a3b3SWei Fang {
137284b4a3b3SWei Fang 	bool old_untagged = !!(entry->untagged_port_bitmap & BIT(port));
137384b4a3b3SWei Fang 
1374751aa5a5SWei Fang 	/* VLAN-unaware VIDs have no egress rules, so return 'false' */
1375751aa5a5SWei Fang 	if (entry->vid >= NETC_VLAN_UNAWARE_PVID(priv->ds->max_num_bridges))
1376751aa5a5SWei Fang 		return false;
1377751aa5a5SWei Fang 
137884b4a3b3SWei Fang 	return old_untagged != untagged;
137984b4a3b3SWei Fang }
138084b4a3b3SWei Fang 
138184b4a3b3SWei Fang static int netc_port_set_vlan_entry(struct netc_port *np, u16 vid,
138284b4a3b3SWei Fang 				    bool untagged)
138384b4a3b3SWei Fang {
138484b4a3b3SWei Fang 	struct netc_switch *priv = np->switch_priv;
138584b4a3b3SWei Fang 	struct netc_vlan_entry *entry;
138684b4a3b3SWei Fang 	struct vft_cfge_data *cfge;
138784b4a3b3SWei Fang 	int port = np->dp->index;
138884b4a3b3SWei Fang 	bool changed;
138984b4a3b3SWei Fang 	int err = 0;
139084b4a3b3SWei Fang 
139184b4a3b3SWei Fang 	mutex_lock(&priv->vft_lock);
139284b4a3b3SWei Fang 
139384b4a3b3SWei Fang 	entry = netc_lookup_vlan_entry(priv, vid);
139484b4a3b3SWei Fang 	if (!entry) {
139584b4a3b3SWei Fang 		err = netc_port_add_vlan_entry(np, vid, untagged);
139684b4a3b3SWei Fang 		goto unlock_vft;
139784b4a3b3SWei Fang 	}
139884b4a3b3SWei Fang 
139984b4a3b3SWei Fang 	/* Check whether the egress VLAN rule is changed */
1400751aa5a5SWei Fang 	changed = netc_port_vlan_egress_rule_changed(priv, entry, port,
1401751aa5a5SWei Fang 						     untagged);
140284b4a3b3SWei Fang 	if (changed) {
140384b4a3b3SWei Fang 		entry->untagged_port_bitmap ^= BIT(port);
140484b4a3b3SWei Fang 		err = netc_port_update_vlan_egress_rule(np, entry);
140584b4a3b3SWei Fang 		if (err) {
140684b4a3b3SWei Fang 			entry->untagged_port_bitmap ^= BIT(port);
140784b4a3b3SWei Fang 			goto unlock_vft;
140884b4a3b3SWei Fang 		}
140984b4a3b3SWei Fang 	}
141084b4a3b3SWei Fang 
141184b4a3b3SWei Fang 	cfge = &entry->cfge;
141284b4a3b3SWei Fang 	if (cfge->bitmap_stg & cpu_to_le32(BIT(port)))
141384b4a3b3SWei Fang 		goto unlock_vft;
141484b4a3b3SWei Fang 
141584b4a3b3SWei Fang 	cfge->bitmap_stg |= cpu_to_le32(BIT(port));
141684b4a3b3SWei Fang 	err = ntmp_vft_update_entry(&priv->ntmp, vid, cfge);
141784b4a3b3SWei Fang 	if (err) {
141884b4a3b3SWei Fang 		dev_err(priv->dev,
141984b4a3b3SWei Fang 			"Failed to update VLAN %u entry on port %d\n",
142084b4a3b3SWei Fang 			vid, port);
142184b4a3b3SWei Fang 
142284b4a3b3SWei Fang 		goto restore_bitmap_stg;
142384b4a3b3SWei Fang 	}
142484b4a3b3SWei Fang 
142584b4a3b3SWei Fang 	mutex_unlock(&priv->vft_lock);
142684b4a3b3SWei Fang 
142784b4a3b3SWei Fang 	return 0;
142884b4a3b3SWei Fang 
142984b4a3b3SWei Fang restore_bitmap_stg:
143084b4a3b3SWei Fang 	cfge->bitmap_stg &= cpu_to_le32(~BIT(port));
143184b4a3b3SWei Fang 	if (changed) {
143284b4a3b3SWei Fang 		entry->untagged_port_bitmap ^= BIT(port);
143384b4a3b3SWei Fang 		/* Recover the corresponding ETT entry. It doesn't matter
143484b4a3b3SWei Fang 		 * if it fails because the bit corresponding to the port
143584b4a3b3SWei Fang 		 * in the port bitmap of the VFT entry is not set. so the
143684b4a3b3SWei Fang 		 * frame will not match that ETT entry.
143784b4a3b3SWei Fang 		 */
143884b4a3b3SWei Fang 		if (netc_port_update_vlan_egress_rule(np, entry))
143984b4a3b3SWei Fang 			entry->untagged_port_bitmap ^= BIT(port);
144084b4a3b3SWei Fang 	}
144184b4a3b3SWei Fang unlock_vft:
144284b4a3b3SWei Fang 	mutex_unlock(&priv->vft_lock);
144384b4a3b3SWei Fang 
144484b4a3b3SWei Fang 	return err;
144584b4a3b3SWei Fang }
144684b4a3b3SWei Fang 
144784b4a3b3SWei Fang static int netc_port_del_vlan_entry(struct netc_port *np, u16 vid)
144884b4a3b3SWei Fang {
144984b4a3b3SWei Fang 	struct netc_switch *priv = np->switch_priv;
145084b4a3b3SWei Fang 	struct netc_vlan_entry *entry;
145184b4a3b3SWei Fang 	struct vft_cfge_data *cfge;
145284b4a3b3SWei Fang 	int port = np->dp->index;
145384b4a3b3SWei Fang 	u32 vlan_port_bitmap;
145484b4a3b3SWei Fang 	int err = 0;
145584b4a3b3SWei Fang 
145684b4a3b3SWei Fang 	mutex_lock(&priv->vft_lock);
145784b4a3b3SWei Fang 
145884b4a3b3SWei Fang 	entry = netc_lookup_vlan_entry(priv, vid);
145984b4a3b3SWei Fang 	if (!entry)
146084b4a3b3SWei Fang 		goto unlock_vft;
146184b4a3b3SWei Fang 
146284b4a3b3SWei Fang 	cfge = &entry->cfge;
146384b4a3b3SWei Fang 	vlan_port_bitmap = FIELD_GET(VFT_PORT_MEMBERSHIP,
146484b4a3b3SWei Fang 				     le32_to_cpu(cfge->bitmap_stg));
1465751aa5a5SWei Fang 	/* If the VID is a VLAN-unaware PVID, we need to clear the CPU
1466751aa5a5SWei Fang 	 * port bit of vlan_port_bitmap, so that the VLAN entry can be
1467751aa5a5SWei Fang 	 * deleted if no user ports use this VLAN.
1468751aa5a5SWei Fang 	 */
1469751aa5a5SWei Fang 	if (dsa_port_is_user(np->dp) &&
1470751aa5a5SWei Fang 	    vid >= NETC_VLAN_UNAWARE_PVID(priv->ds->max_num_bridges)) {
1471751aa5a5SWei Fang 		struct dsa_port *cpu_dp = np->dp->cpu_dp;
1472751aa5a5SWei Fang 
1473751aa5a5SWei Fang 		vlan_port_bitmap &= ~BIT(cpu_dp->index);
1474751aa5a5SWei Fang 	}
1475751aa5a5SWei Fang 
147684b4a3b3SWei Fang 	/* If the VLAN only belongs to the current port */
147784b4a3b3SWei Fang 	if (vlan_port_bitmap == BIT(port)) {
147884b4a3b3SWei Fang 		err = ntmp_vft_delete_entry(&priv->ntmp, vid);
147984b4a3b3SWei Fang 		if (err)
148084b4a3b3SWei Fang 			goto unlock_vft;
148184b4a3b3SWei Fang 
148284b4a3b3SWei Fang 		netc_delete_vlan_egress_rule(priv, entry);
148384b4a3b3SWei Fang 		netc_del_vlan_entry(entry);
148484b4a3b3SWei Fang 
148584b4a3b3SWei Fang 		goto unlock_vft;
148684b4a3b3SWei Fang 	}
148784b4a3b3SWei Fang 
148884b4a3b3SWei Fang 	if (!(vlan_port_bitmap & BIT(port)))
148984b4a3b3SWei Fang 		goto unlock_vft;
149084b4a3b3SWei Fang 
149184b4a3b3SWei Fang 	cfge->bitmap_stg &= cpu_to_le32(~BIT(port));
149284b4a3b3SWei Fang 	err = ntmp_vft_update_entry(&priv->ntmp, vid, cfge);
149384b4a3b3SWei Fang 	if (err) {
149484b4a3b3SWei Fang 		cfge->bitmap_stg |= cpu_to_le32(BIT(port));
149584b4a3b3SWei Fang 		goto unlock_vft;
149684b4a3b3SWei Fang 	}
149784b4a3b3SWei Fang 
149884b4a3b3SWei Fang unlock_vft:
149984b4a3b3SWei Fang 	mutex_unlock(&priv->vft_lock);
150084b4a3b3SWei Fang 
150184b4a3b3SWei Fang 	return err;
150284b4a3b3SWei Fang }
150384b4a3b3SWei Fang 
150446d64076SWei Fang static int netc_port_enable(struct dsa_switch *ds, int port,
150546d64076SWei Fang 			    struct phy_device *phy)
150646d64076SWei Fang {
150746d64076SWei Fang 	struct netc_port *np = NETC_PORT(ds, port);
150846d64076SWei Fang 	int err;
150946d64076SWei Fang 
151046d64076SWei Fang 	if (np->enable)
151146d64076SWei Fang 		return 0;
151246d64076SWei Fang 
151346d64076SWei Fang 	err = clk_prepare_enable(np->ref_clk);
151446d64076SWei Fang 	if (err) {
151546d64076SWei Fang 		dev_err(ds->dev,
151646d64076SWei Fang 			"Failed to enable enet_ref_clk of port %d\n", port);
151746d64076SWei Fang 		return err;
151846d64076SWei Fang 	}
151946d64076SWei Fang 
152046d64076SWei Fang 	np->enable = true;
152146d64076SWei Fang 
152246d64076SWei Fang 	return 0;
152346d64076SWei Fang }
152446d64076SWei Fang 
152546d64076SWei Fang static void netc_port_disable(struct dsa_switch *ds, int port)
152646d64076SWei Fang {
152746d64076SWei Fang 	struct netc_port *np = NETC_PORT(ds, port);
152846d64076SWei Fang 
152946d64076SWei Fang 	/* When .port_disable() is called, .port_enable() may not have been
153046d64076SWei Fang 	 * called. In this case, both the prepare_count and enable_count of
153146d64076SWei Fang 	 * clock are 0. Calling clk_disable_unprepare() at this time will
153246d64076SWei Fang 	 * cause warnings.
153346d64076SWei Fang 	 */
153446d64076SWei Fang 	if (!np->enable)
153546d64076SWei Fang 		return;
153646d64076SWei Fang 
153746d64076SWei Fang 	clk_disable_unprepare(np->ref_clk);
153846d64076SWei Fang 	np->enable = false;
153946d64076SWei Fang }
154046d64076SWei Fang 
154146d64076SWei Fang static void netc_port_stp_state_set(struct dsa_switch *ds,
154246d64076SWei Fang 				    int port, u8 state)
154346d64076SWei Fang {
154446d64076SWei Fang 	struct netc_port *np = NETC_PORT(ds, port);
154546d64076SWei Fang 	u32 val;
154646d64076SWei Fang 
154746d64076SWei Fang 	switch (state) {
154846d64076SWei Fang 	case BR_STATE_DISABLED:
154946d64076SWei Fang 	case BR_STATE_LISTENING:
155046d64076SWei Fang 	case BR_STATE_BLOCKING:
155146d64076SWei Fang 		val = NETC_STG_STATE_DISABLED;
155246d64076SWei Fang 		break;
155346d64076SWei Fang 	case BR_STATE_LEARNING:
155446d64076SWei Fang 		val = NETC_STG_STATE_LEARNING;
155546d64076SWei Fang 		break;
155646d64076SWei Fang 	case BR_STATE_FORWARDING:
155746d64076SWei Fang 		val = NETC_STG_STATE_FORWARDING;
155846d64076SWei Fang 		break;
155946d64076SWei Fang 	default:
156046d64076SWei Fang 		return;
156146d64076SWei Fang 	}
156246d64076SWei Fang 
156346d64076SWei Fang 	netc_port_wr(np, NETC_BPSTGSR, val);
156446d64076SWei Fang }
156546d64076SWei Fang 
156646d64076SWei Fang static int netc_port_change_mtu(struct dsa_switch *ds,
156746d64076SWei Fang 				int port, int mtu)
156846d64076SWei Fang {
156946d64076SWei Fang 	u32 max_frame_size = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
157046d64076SWei Fang 
157146d64076SWei Fang 	netc_port_set_max_frame_size(NETC_PORT(ds, port), max_frame_size);
157246d64076SWei Fang 
157346d64076SWei Fang 	return 0;
157446d64076SWei Fang }
157546d64076SWei Fang 
157646d64076SWei Fang static int netc_port_max_mtu(struct dsa_switch *ds, int port)
157746d64076SWei Fang {
157846d64076SWei Fang 	return NETC_MAX_FRAME_LEN - VLAN_ETH_HLEN - ETH_FCS_LEN;
157946d64076SWei Fang }
158046d64076SWei Fang 
1581751aa5a5SWei Fang static struct net_device *netc_classify_db(struct dsa_db db)
1582751aa5a5SWei Fang {
1583751aa5a5SWei Fang 	switch (db.type) {
1584751aa5a5SWei Fang 	case DSA_DB_PORT:
1585751aa5a5SWei Fang 		return NULL;
1586751aa5a5SWei Fang 	case DSA_DB_BRIDGE:
1587751aa5a5SWei Fang 		return db.bridge.dev;
1588751aa5a5SWei Fang 	default:
1589751aa5a5SWei Fang 		return ERR_PTR(-EOPNOTSUPP);
1590751aa5a5SWei Fang 	}
1591751aa5a5SWei Fang }
1592751aa5a5SWei Fang 
1593751aa5a5SWei Fang static u16 netc_vlan_unaware_pvid(struct dsa_bridge *bridge)
1594751aa5a5SWei Fang {
1595751aa5a5SWei Fang 	u32 br_num;
1596751aa5a5SWei Fang 
1597751aa5a5SWei Fang 	if (!bridge)
1598751aa5a5SWei Fang 		return NETC_STANDALONE_PVID;
1599751aa5a5SWei Fang 
1600751aa5a5SWei Fang 	br_num = bridge->num;
1601751aa5a5SWei Fang 
1602751aa5a5SWei Fang 	/* The br_num is supposed to be 1 ~ ds->max_num_bridges, see
1603751aa5a5SWei Fang 	 * dsa_bridge_num_get(). Since max_num_bridges is non-zero,
1604751aa5a5SWei Fang 	 * so dsa_port_bridge_create() will return an error if
1605751aa5a5SWei Fang 	 * dsa_bridge_num_get() returns 0.
1606751aa5a5SWei Fang 	 */
1607751aa5a5SWei Fang 	if (WARN_ON(!br_num))
1608751aa5a5SWei Fang 		return NETC_STANDALONE_PVID;
1609751aa5a5SWei Fang 
1610751aa5a5SWei Fang 	return NETC_VLAN_UNAWARE_PVID(br_num);
1611751aa5a5SWei Fang }
1612751aa5a5SWei Fang 
161346d64076SWei Fang static int netc_port_fdb_add(struct dsa_switch *ds, int port,
161446d64076SWei Fang 			     const unsigned char *addr, u16 vid,
161546d64076SWei Fang 			     struct dsa_db db)
161646d64076SWei Fang {
1617751aa5a5SWei Fang 	struct net_device *br_ndev = netc_classify_db(db);
161846d64076SWei Fang 	struct netc_port *np = NETC_PORT(ds, port);
161946d64076SWei Fang 
1620751aa5a5SWei Fang 	if (IS_ERR(br_ndev))
1621751aa5a5SWei Fang 		return PTR_ERR(br_ndev);
1622751aa5a5SWei Fang 
1623751aa5a5SWei Fang 	if (!vid)
1624751aa5a5SWei Fang 		vid = netc_vlan_unaware_pvid(br_ndev ? &db.bridge : NULL);
162546d64076SWei Fang 
162646d64076SWei Fang 	return netc_port_set_fdb_entry(np, addr, vid);
162746d64076SWei Fang }
162846d64076SWei Fang 
162946d64076SWei Fang static int netc_port_fdb_del(struct dsa_switch *ds, int port,
163046d64076SWei Fang 			     const unsigned char *addr, u16 vid,
163146d64076SWei Fang 			     struct dsa_db db)
163246d64076SWei Fang {
1633751aa5a5SWei Fang 	struct net_device *br_ndev = netc_classify_db(db);
163446d64076SWei Fang 	struct netc_port *np = NETC_PORT(ds, port);
163546d64076SWei Fang 
1636751aa5a5SWei Fang 	if (IS_ERR(br_ndev))
1637751aa5a5SWei Fang 		return PTR_ERR(br_ndev);
1638751aa5a5SWei Fang 
1639751aa5a5SWei Fang 	if (!vid)
1640751aa5a5SWei Fang 		vid = netc_vlan_unaware_pvid(br_ndev ? &db.bridge : NULL);
164146d64076SWei Fang 
164246d64076SWei Fang 	return netc_port_del_fdb_entry(np, addr, vid);
164346d64076SWei Fang }
164446d64076SWei Fang 
164546d64076SWei Fang static int netc_port_fdb_dump(struct dsa_switch *ds, int port,
164646d64076SWei Fang 			      dsa_fdb_dump_cb_t *cb, void *data)
164746d64076SWei Fang {
164846d64076SWei Fang 	struct netc_switch *priv = ds->priv;
164946d64076SWei Fang 	u32 resume_eid = NTMP_NULL_ENTRY_ID;
165046d64076SWei Fang 	struct fdbt_entry_data *entry;
165146d64076SWei Fang 	struct fdbt_keye_data *keye;
165246d64076SWei Fang 	struct fdbt_cfge_data *cfge;
165346d64076SWei Fang 	u32 cfg, cnt = 0;
165446d64076SWei Fang 	bool is_static;
165546d64076SWei Fang 	int err;
165646d64076SWei Fang 	u16 vid;
165746d64076SWei Fang 
165846d64076SWei Fang 	entry = kmalloc_obj(*entry);
165946d64076SWei Fang 	if (!entry)
166046d64076SWei Fang 		return -ENOMEM;
166146d64076SWei Fang 
166246d64076SWei Fang 	keye = &entry->keye;
166346d64076SWei Fang 	cfge = &entry->cfge;
166446d64076SWei Fang 	mutex_lock(&priv->fdbt_lock);
166546d64076SWei Fang 
166646d64076SWei Fang 	do {
166746d64076SWei Fang 		memset(entry, 0, sizeof(*entry));
166846d64076SWei Fang 		err = ntmp_fdbt_search_port_entry(&priv->ntmp, port,
166946d64076SWei Fang 						  &resume_eid, entry);
167046d64076SWei Fang 		if (err || entry->entry_id == NTMP_NULL_ENTRY_ID)
167146d64076SWei Fang 			break;
167246d64076SWei Fang 
167346d64076SWei Fang 		cfg = le32_to_cpu(cfge->cfg);
167446d64076SWei Fang 		is_static = (cfg & FDBT_DYNAMIC) ? false : true;
167546d64076SWei Fang 		vid = le16_to_cpu(keye->fid);
1676751aa5a5SWei Fang 		if (vid >= NETC_VLAN_UNAWARE_PVID(ds->max_num_bridges))
1677751aa5a5SWei Fang 			vid = 0;
167846d64076SWei Fang 
167946d64076SWei Fang 		err = cb(keye->mac_addr, vid, is_static, data);
168046d64076SWei Fang 		if (err)
168146d64076SWei Fang 			break;
168246d64076SWei Fang 
168346d64076SWei Fang 		/* To prevent hardware malfunctions from causing an
168446d64076SWei Fang 		 * infinite loop.
168546d64076SWei Fang 		 */
168646d64076SWei Fang 		if (++cnt >= priv->htmcapr_num_words)
168746d64076SWei Fang 			break;
168846d64076SWei Fang 	} while (resume_eid != NTMP_NULL_ENTRY_ID);
168946d64076SWei Fang 
169046d64076SWei Fang 	mutex_unlock(&priv->fdbt_lock);
169146d64076SWei Fang 	kfree(entry);
169246d64076SWei Fang 
169346d64076SWei Fang 	return err;
169446d64076SWei Fang }
169546d64076SWei Fang 
169646d64076SWei Fang static int netc_port_mdb_add(struct dsa_switch *ds, int port,
169746d64076SWei Fang 			     const struct switchdev_obj_port_mdb *mdb,
169846d64076SWei Fang 			     struct dsa_db db)
169946d64076SWei Fang {
170046d64076SWei Fang 	return netc_port_fdb_add(ds, port, mdb->addr, mdb->vid, db);
170146d64076SWei Fang }
170246d64076SWei Fang 
170346d64076SWei Fang static int netc_port_mdb_del(struct dsa_switch *ds, int port,
170446d64076SWei Fang 			     const struct switchdev_obj_port_mdb *mdb,
170546d64076SWei Fang 			     struct dsa_db db)
170646d64076SWei Fang {
170746d64076SWei Fang 	return netc_port_fdb_del(ds, port, mdb->addr, mdb->vid, db);
170846d64076SWei Fang }
170946d64076SWei Fang 
171046d64076SWei Fang static int netc_port_add_host_flood_rule(struct netc_port *np,
171146d64076SWei Fang 					 bool uc, bool mc)
171246d64076SWei Fang {
171346d64076SWei Fang 	const u8 dmac_mask[ETH_ALEN] = {0x1, 0, 0, 0, 0, 0};
171446d64076SWei Fang 	struct netc_switch *priv = np->switch_priv;
171546d64076SWei Fang 	struct ipft_entry_data *host_flood;
171646d64076SWei Fang 	struct ipft_keye_data *keye;
171746d64076SWei Fang 	struct ipft_cfge_data *cfge;
171846d64076SWei Fang 	u16 src_port;
171946d64076SWei Fang 	u32 cfg;
172046d64076SWei Fang 	int err;
172146d64076SWei Fang 
172246d64076SWei Fang 	if (!uc && !mc) {
172346d64076SWei Fang 		/* Disable ingress port filter table lookup */
172446d64076SWei Fang 		netc_port_wr(np, NETC_PIPFCR, 0);
172546d64076SWei Fang 		np->uc = false;
172646d64076SWei Fang 		np->mc = false;
172746d64076SWei Fang 
172846d64076SWei Fang 		return 0;
172946d64076SWei Fang 	}
173046d64076SWei Fang 
173146d64076SWei Fang 	host_flood = kzalloc_obj(*host_flood);
173246d64076SWei Fang 	if (!host_flood)
173346d64076SWei Fang 		return -ENOMEM;
173446d64076SWei Fang 
173546d64076SWei Fang 	keye = &host_flood->keye;
173646d64076SWei Fang 	cfge = &host_flood->cfge;
173746d64076SWei Fang 
173846d64076SWei Fang 	src_port = FIELD_PREP(IPFT_SRC_PORT, np->dp->index);
173946d64076SWei Fang 	src_port |= IPFT_SRC_PORT_MASK;
174046d64076SWei Fang 	keye->src_port = cpu_to_le16(src_port);
174146d64076SWei Fang 
174246d64076SWei Fang 	/* If either only unicast or only multicast need to be flooded
174346d64076SWei Fang 	 * to the host, we always set the mask that tests the first MAC
174446d64076SWei Fang 	 * DA octet. The value should be 0 for the first bit (if unicast
174546d64076SWei Fang 	 * has to be flooded) or 1 (if multicast). If both unicast and
174646d64076SWei Fang 	 * multicast have to be flooded, we leave the key mask empty, so
174746d64076SWei Fang 	 * it matches everything.
174846d64076SWei Fang 	 */
174946d64076SWei Fang 	if (uc && !mc)
175046d64076SWei Fang 		ether_addr_copy(keye->dmac_mask, dmac_mask);
175146d64076SWei Fang 
175246d64076SWei Fang 	if (!uc && mc) {
175346d64076SWei Fang 		ether_addr_copy(keye->dmac, dmac_mask);
175446d64076SWei Fang 		ether_addr_copy(keye->dmac_mask, dmac_mask);
175546d64076SWei Fang 	}
175646d64076SWei Fang 
175746d64076SWei Fang 	cfg = FIELD_PREP(IPFT_FLTFA, IPFT_FLTFA_REDIRECT);
175846d64076SWei Fang 	cfg |= FIELD_PREP(IPFT_HR, NETC_HR_HOST_FLOOD);
175946d64076SWei Fang 	cfge->cfg = cpu_to_le32(cfg);
176046d64076SWei Fang 
176146d64076SWei Fang 	err = ntmp_ipft_add_entry(&priv->ntmp, host_flood);
176246d64076SWei Fang 	if (err) {
176346d64076SWei Fang 		kfree(host_flood);
176446d64076SWei Fang 		return err;
176546d64076SWei Fang 	}
176646d64076SWei Fang 
176746d64076SWei Fang 	np->uc = uc;
176846d64076SWei Fang 	np->mc = mc;
176946d64076SWei Fang 	np->host_flood = host_flood;
177046d64076SWei Fang 	/* Enable ingress port filter table lookup */
177146d64076SWei Fang 	netc_port_wr(np, NETC_PIPFCR, PIPFCR_EN);
177246d64076SWei Fang 
177346d64076SWei Fang 	return 0;
177446d64076SWei Fang }
177546d64076SWei Fang 
177646d64076SWei Fang static void netc_port_remove_host_flood(struct netc_port *np,
177746d64076SWei Fang 					struct ipft_entry_data *host_flood)
177846d64076SWei Fang {
177946d64076SWei Fang 	struct netc_switch *priv = np->switch_priv;
1780751aa5a5SWei Fang 	bool disable_host_flood = false;
178146d64076SWei Fang 
178246d64076SWei Fang 	if (!host_flood)
178346d64076SWei Fang 		return;
178446d64076SWei Fang 
1785751aa5a5SWei Fang 	if (np->host_flood == host_flood)
1786751aa5a5SWei Fang 		disable_host_flood = true;
1787751aa5a5SWei Fang 
178846d64076SWei Fang 	ntmp_ipft_delete_entry(&priv->ntmp, host_flood->entry_id);
178946d64076SWei Fang 	kfree(host_flood);
1790751aa5a5SWei Fang 
1791751aa5a5SWei Fang 	if (disable_host_flood) {
1792751aa5a5SWei Fang 		np->host_flood = NULL;
1793751aa5a5SWei Fang 		np->uc = false;
1794751aa5a5SWei Fang 		np->mc = false;
1795751aa5a5SWei Fang 		netc_port_wr(np, NETC_PIPFCR, 0);
1796751aa5a5SWei Fang 	}
179746d64076SWei Fang }
179846d64076SWei Fang 
179946d64076SWei Fang static void netc_port_set_host_flood(struct dsa_switch *ds, int port,
180046d64076SWei Fang 				     bool uc, bool mc)
180146d64076SWei Fang {
180246d64076SWei Fang 	struct netc_port *np = NETC_PORT(ds, port);
180346d64076SWei Fang 	struct ipft_entry_data *old_host_flood;
180446d64076SWei Fang 
1805751aa5a5SWei Fang 	/* Do not add host flood rule to ingress port filter table when
1806751aa5a5SWei Fang 	 * the port has joined a bridge. Otherwise, the ingress frames
1807751aa5a5SWei Fang 	 * will bypass FDB table lookup and MAC learning, so the frames
1808751aa5a5SWei Fang 	 * will be redirected directly to the CPU port.
1809751aa5a5SWei Fang 	 */
1810751aa5a5SWei Fang 	if (dsa_port_bridge_dev_get(np->dp)) {
1811751aa5a5SWei Fang 		netc_port_remove_host_flood(np, np->host_flood);
1812751aa5a5SWei Fang 
1813751aa5a5SWei Fang 		return;
1814751aa5a5SWei Fang 	}
1815751aa5a5SWei Fang 
181646d64076SWei Fang 	if (np->uc == uc && np->mc == mc)
181746d64076SWei Fang 		return;
181846d64076SWei Fang 
181946d64076SWei Fang 	/* IPFT does not support in-place updates to the KEYE element,
182046d64076SWei Fang 	 * we need to add a new entry and then delete the old one. So
182146d64076SWei Fang 	 * save the old entry first.
182246d64076SWei Fang 	 */
182346d64076SWei Fang 	old_host_flood = np->host_flood;
182446d64076SWei Fang 	np->host_flood = NULL;
182546d64076SWei Fang 
182646d64076SWei Fang 	if (netc_port_add_host_flood_rule(np, uc, mc)) {
182746d64076SWei Fang 		np->host_flood = old_host_flood;
182846d64076SWei Fang 		dev_err(ds->dev, "Failed to add host flood rule on port %d\n",
182946d64076SWei Fang 			port);
183046d64076SWei Fang 		return;
183146d64076SWei Fang 	}
183246d64076SWei Fang 
183346d64076SWei Fang 	/* Remove the old host flood entry */
183446d64076SWei Fang 	netc_port_remove_host_flood(np, old_host_flood);
183546d64076SWei Fang }
183646d64076SWei Fang 
1837751aa5a5SWei Fang static int netc_single_vlan_aware_bridge(struct dsa_switch *ds,
1838751aa5a5SWei Fang 					 struct netlink_ext_ack *extack)
1839751aa5a5SWei Fang {
1840751aa5a5SWei Fang 	struct net_device *br_ndev = NULL;
1841751aa5a5SWei Fang 	struct dsa_port *dp;
1842751aa5a5SWei Fang 
1843751aa5a5SWei Fang 	dsa_switch_for_each_available_port(dp, ds) {
1844751aa5a5SWei Fang 		struct net_device *port_br = dsa_port_bridge_dev_get(dp);
1845751aa5a5SWei Fang 
1846751aa5a5SWei Fang 		if (!port_br || !br_vlan_enabled(port_br))
1847751aa5a5SWei Fang 			continue;
1848751aa5a5SWei Fang 
1849751aa5a5SWei Fang 		if (!br_ndev) {
1850751aa5a5SWei Fang 			br_ndev = port_br;
1851751aa5a5SWei Fang 			continue;
1852751aa5a5SWei Fang 		}
1853751aa5a5SWei Fang 
1854751aa5a5SWei Fang 		if (br_ndev == port_br)
1855751aa5a5SWei Fang 			continue;
1856751aa5a5SWei Fang 
1857751aa5a5SWei Fang 		NL_SET_ERR_MSG_MOD(extack,
1858751aa5a5SWei Fang 				   "Only one VLAN-aware bridge is supported");
1859751aa5a5SWei Fang 
1860751aa5a5SWei Fang 		return -EBUSY;
1861751aa5a5SWei Fang 	}
1862751aa5a5SWei Fang 
1863751aa5a5SWei Fang 	return 0;
1864751aa5a5SWei Fang }
1865751aa5a5SWei Fang 
1866751aa5a5SWei Fang static int netc_port_vlan_filtering(struct dsa_switch *ds,
1867751aa5a5SWei Fang 				    int port, bool vlan_aware,
1868751aa5a5SWei Fang 				    struct netlink_ext_ack *extack)
1869751aa5a5SWei Fang {
1870751aa5a5SWei Fang 	struct netc_port *np = NETC_PORT(ds, port);
1871751aa5a5SWei Fang 	u16 pvid;
1872751aa5a5SWei Fang 	int err;
1873751aa5a5SWei Fang 
1874751aa5a5SWei Fang 	/* Before calling port_vlan_filtering(), br_vlan_filter_toggle() has
1875751aa5a5SWei Fang 	 * already updated the BROPT_VLAN_ENABLED bit of br->options. So the
1876751aa5a5SWei Fang 	 * VLAN filtering status of the switch ports can be checked by the
1877751aa5a5SWei Fang 	 * br_vlan_enabled() function.
1878751aa5a5SWei Fang 	 */
1879751aa5a5SWei Fang 	err = netc_single_vlan_aware_bridge(ds, extack);
1880751aa5a5SWei Fang 	if (err)
1881751aa5a5SWei Fang 		return err;
1882751aa5a5SWei Fang 
1883751aa5a5SWei Fang 	pvid = netc_vlan_unaware_pvid(np->dp->bridge);
1884751aa5a5SWei Fang 	if (pvid == NETC_STANDALONE_PVID) {
1885751aa5a5SWei Fang 		vlan_aware = false;
1886751aa5a5SWei Fang 		goto bpdvr_config;
1887751aa5a5SWei Fang 	}
1888751aa5a5SWei Fang 
1889751aa5a5SWei Fang 	if (vlan_aware) {
1890751aa5a5SWei Fang 		/* The FDB entries associated with unaware_pvid do not need
1891751aa5a5SWei Fang 		 * to be deleted, so that when switching from VLAN-aware to
1892751aa5a5SWei Fang 		 * VLAN-unaware mode, these FDB entries do not need to be
1893751aa5a5SWei Fang 		 * re-added.
1894751aa5a5SWei Fang 		 */
1895751aa5a5SWei Fang 		err = netc_port_del_vlan_entry(np, pvid);
1896751aa5a5SWei Fang 		if (err)
1897751aa5a5SWei Fang 			return err;
1898751aa5a5SWei Fang 
1899751aa5a5SWei Fang 		pvid = np->pvid;
1900751aa5a5SWei Fang 	} else {
1901751aa5a5SWei Fang 		err = netc_port_set_vlan_entry(np, pvid, false);
1902751aa5a5SWei Fang 		if (err)
1903751aa5a5SWei Fang 			return err;
1904751aa5a5SWei Fang 	}
1905751aa5a5SWei Fang 
1906751aa5a5SWei Fang bpdvr_config:
1907751aa5a5SWei Fang 	netc_port_set_vlan_aware(np, vlan_aware);
1908751aa5a5SWei Fang 	netc_port_set_pvid(np, pvid);
1909751aa5a5SWei Fang 
1910751aa5a5SWei Fang 	return 0;
1911751aa5a5SWei Fang }
1912751aa5a5SWei Fang 
191384b4a3b3SWei Fang static int netc_port_vlan_add(struct dsa_switch *ds, int port,
191484b4a3b3SWei Fang 			      const struct switchdev_obj_port_vlan *vlan,
191584b4a3b3SWei Fang 			      struct netlink_ext_ack *extack)
191684b4a3b3SWei Fang {
191784b4a3b3SWei Fang 	struct netc_port *np = NETC_PORT(ds, port);
1918751aa5a5SWei Fang 	struct dsa_port *dp = np->dp;
191984b4a3b3SWei Fang 	bool untagged;
1920751aa5a5SWei Fang 	int err;
192184b4a3b3SWei Fang 
192284b4a3b3SWei Fang 	/* The 8021q layer may attempt to change NETC_STANDALONE_PVID
192384b4a3b3SWei Fang 	 * (VID 0), so we need to ignore it.
192484b4a3b3SWei Fang 	 */
192584b4a3b3SWei Fang 	if (vlan->vid == NETC_STANDALONE_PVID)
192684b4a3b3SWei Fang 		return 0;
192784b4a3b3SWei Fang 
1928751aa5a5SWei Fang 	if (vlan->vid >= NETC_VLAN_UNAWARE_PVID(ds->max_num_bridges)) {
1929751aa5a5SWei Fang 		NL_SET_ERR_MSG_FMT_MOD(extack,
1930751aa5a5SWei Fang 				       "VID %d~4095 reserved for VLAN-unaware bridge",
1931751aa5a5SWei Fang 				       NETC_VLAN_UNAWARE_PVID(ds->max_num_bridges));
1932751aa5a5SWei Fang 		return -EINVAL;
1933751aa5a5SWei Fang 	}
193484b4a3b3SWei Fang 
1935751aa5a5SWei Fang 	untagged = !!(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
1936751aa5a5SWei Fang 	err = netc_port_set_vlan_entry(np, vlan->vid, untagged);
1937751aa5a5SWei Fang 	if (err)
1938751aa5a5SWei Fang 		return err;
1939751aa5a5SWei Fang 
1940751aa5a5SWei Fang 	if (vlan->flags & BRIDGE_VLAN_INFO_PVID) {
1941751aa5a5SWei Fang 		np->pvid = vlan->vid;
1942751aa5a5SWei Fang 		if (dsa_port_is_vlan_filtering(dp))
1943751aa5a5SWei Fang 			netc_port_set_pvid(np, vlan->vid);
1944751aa5a5SWei Fang 
1945751aa5a5SWei Fang 		return 0;
1946751aa5a5SWei Fang 	}
1947751aa5a5SWei Fang 
1948751aa5a5SWei Fang 	if (np->pvid != vlan->vid)
1949751aa5a5SWei Fang 		return 0;
1950751aa5a5SWei Fang 
1951751aa5a5SWei Fang 	/* Delete PVID */
1952751aa5a5SWei Fang 	np->pvid = NETC_STANDALONE_PVID;
1953751aa5a5SWei Fang 	if (dsa_port_is_vlan_filtering(dp))
1954751aa5a5SWei Fang 		netc_port_set_pvid(np, NETC_STANDALONE_PVID);
1955751aa5a5SWei Fang 
1956751aa5a5SWei Fang 	return 0;
195784b4a3b3SWei Fang }
195884b4a3b3SWei Fang 
195984b4a3b3SWei Fang static int netc_port_vlan_del(struct dsa_switch *ds, int port,
196084b4a3b3SWei Fang 			      const struct switchdev_obj_port_vlan *vlan)
196184b4a3b3SWei Fang {
196284b4a3b3SWei Fang 	struct netc_port *np = NETC_PORT(ds, port);
1963751aa5a5SWei Fang 	int err;
196484b4a3b3SWei Fang 
196584b4a3b3SWei Fang 	if (vlan->vid == NETC_STANDALONE_PVID)
196684b4a3b3SWei Fang 		return 0;
196784b4a3b3SWei Fang 
1968751aa5a5SWei Fang 	if (vlan->vid >= NETC_VLAN_UNAWARE_PVID(ds->max_num_bridges))
1969751aa5a5SWei Fang 		return -EINVAL;
1970751aa5a5SWei Fang 
1971751aa5a5SWei Fang 	err = netc_port_del_vlan_entry(np, vlan->vid);
1972751aa5a5SWei Fang 	if (err)
1973751aa5a5SWei Fang 		return err;
1974751aa5a5SWei Fang 
1975751aa5a5SWei Fang 	if (np->pvid == vlan->vid) {
1976751aa5a5SWei Fang 		np->pvid = NETC_STANDALONE_PVID;
1977751aa5a5SWei Fang 
1978751aa5a5SWei Fang 		/* Set the port PVID to NETC_STANDALONE_PVID if the VLAN-aware
1979751aa5a5SWei Fang 		 * bridge port has no PVID. The untagged frames will not be
1980751aa5a5SWei Fang 		 * forwarded to other user ports, as NETC_STANDALONE_PVID VLAN
1981751aa5a5SWei Fang 		 * entry has disabled MAC learning and flooding, and other user
1982751aa5a5SWei Fang 		 * ports do not have FDB entries with NETC_STANDALONE_PVID.
1983751aa5a5SWei Fang 		 */
1984751aa5a5SWei Fang 		if (dsa_port_is_vlan_filtering(np->dp))
1985751aa5a5SWei Fang 			netc_port_set_pvid(np, NETC_STANDALONE_PVID);
1986751aa5a5SWei Fang 	}
1987751aa5a5SWei Fang 
1988751aa5a5SWei Fang 	return 0;
1989751aa5a5SWei Fang }
1990751aa5a5SWei Fang 
1991751aa5a5SWei Fang static int netc_port_bridge_join(struct dsa_switch *ds, int port,
1992751aa5a5SWei Fang 				 struct dsa_bridge bridge,
1993751aa5a5SWei Fang 				 bool *tx_fwd_offload,
1994751aa5a5SWei Fang 				 struct netlink_ext_ack *extack)
1995751aa5a5SWei Fang {
1996751aa5a5SWei Fang 	struct netc_port *np = NETC_PORT(ds, port);
1997*05b5ee61SWei Fang 	struct netc_switch *priv = ds->priv;
1998751aa5a5SWei Fang 	u16 vlan_unaware_pvid;
1999751aa5a5SWei Fang 	int err;
2000751aa5a5SWei Fang 
2001751aa5a5SWei Fang 	if (!bridge.num) {
2002751aa5a5SWei Fang 		NL_SET_ERR_MSG_MOD(extack, "Bridge number 0 is unsupported");
2003751aa5a5SWei Fang 		return -EINVAL;
2004751aa5a5SWei Fang 	}
2005751aa5a5SWei Fang 
2006751aa5a5SWei Fang 	err = netc_single_vlan_aware_bridge(ds, extack);
2007751aa5a5SWei Fang 	if (err)
2008751aa5a5SWei Fang 		return err;
2009751aa5a5SWei Fang 
2010751aa5a5SWei Fang 	netc_port_set_mlo(np, MLO_NOT_OVERRIDE);
2011751aa5a5SWei Fang 
2012751aa5a5SWei Fang 	if (br_vlan_enabled(bridge.dev))
2013751aa5a5SWei Fang 		goto out;
2014751aa5a5SWei Fang 
2015751aa5a5SWei Fang 	vlan_unaware_pvid = NETC_VLAN_UNAWARE_PVID(bridge.num);
2016751aa5a5SWei Fang 	err = netc_port_set_vlan_entry(np, vlan_unaware_pvid, false);
2017751aa5a5SWei Fang 	if (err)
2018751aa5a5SWei Fang 		goto disable_mlo;
2019751aa5a5SWei Fang 
2020751aa5a5SWei Fang 	netc_port_set_pvid(np, vlan_unaware_pvid);
2021751aa5a5SWei Fang 
2022751aa5a5SWei Fang out:
2023751aa5a5SWei Fang 	netc_port_remove_host_flood(np, np->host_flood);
2024751aa5a5SWei Fang 
2025*05b5ee61SWei Fang 	if (atomic_inc_return(&priv->br_cnt) == 1)
2026*05b5ee61SWei Fang 		schedule_delayed_work(&priv->fdbt_ageing_work,
2027*05b5ee61SWei Fang 				      READ_ONCE(priv->fdbt_ageing_delay));
2028*05b5ee61SWei Fang 
2029751aa5a5SWei Fang 	return 0;
2030751aa5a5SWei Fang 
2031751aa5a5SWei Fang disable_mlo:
2032751aa5a5SWei Fang 	netc_port_set_mlo(np, MLO_DISABLE);
2033751aa5a5SWei Fang 
2034751aa5a5SWei Fang 	return err;
2035751aa5a5SWei Fang }
2036751aa5a5SWei Fang 
2037751aa5a5SWei Fang static void netc_port_remove_dynamic_entries(struct netc_port *np)
2038751aa5a5SWei Fang {
2039751aa5a5SWei Fang 	struct netc_switch *priv = np->switch_priv;
2040751aa5a5SWei Fang 
2041751aa5a5SWei Fang 	/* Return if the port is not available */
2042751aa5a5SWei Fang 	if (!np->dp)
2043751aa5a5SWei Fang 		return;
2044751aa5a5SWei Fang 
2045751aa5a5SWei Fang 	mutex_lock(&priv->fdbt_lock);
2046751aa5a5SWei Fang 	ntmp_fdbt_delete_port_dynamic_entries(&priv->ntmp, np->dp->index);
2047751aa5a5SWei Fang 	mutex_unlock(&priv->fdbt_lock);
2048751aa5a5SWei Fang }
2049751aa5a5SWei Fang 
2050751aa5a5SWei Fang static void netc_port_bridge_leave(struct dsa_switch *ds, int port,
2051751aa5a5SWei Fang 				   struct dsa_bridge bridge)
2052751aa5a5SWei Fang {
2053751aa5a5SWei Fang 	struct netc_port *np = NETC_PORT(ds, port);
2054751aa5a5SWei Fang 	struct net_device *ndev = np->dp->user;
2055*05b5ee61SWei Fang 	struct netc_switch *priv = ds->priv;
2056751aa5a5SWei Fang 	u16 vlan_unaware_pvid;
2057751aa5a5SWei Fang 	bool mc, uc;
2058751aa5a5SWei Fang 
2059751aa5a5SWei Fang 	netc_port_set_mlo(np, MLO_DISABLE);
2060751aa5a5SWei Fang 	netc_port_set_pvid(np, NETC_STANDALONE_PVID);
2061751aa5a5SWei Fang 	np->pvid = NETC_STANDALONE_PVID;
2062751aa5a5SWei Fang 
2063*05b5ee61SWei Fang 	if (atomic_dec_and_test(&priv->br_cnt))
2064*05b5ee61SWei Fang 		cancel_delayed_work_sync(&priv->fdbt_ageing_work);
2065*05b5ee61SWei Fang 
2066751aa5a5SWei Fang 	netc_port_remove_dynamic_entries(np);
2067751aa5a5SWei Fang 	uc = ndev->flags & IFF_PROMISC;
2068751aa5a5SWei Fang 	mc = ndev->flags & (IFF_PROMISC | IFF_ALLMULTI);
2069751aa5a5SWei Fang 
2070751aa5a5SWei Fang 	if (netc_port_add_host_flood_rule(np, uc, mc))
2071751aa5a5SWei Fang 		dev_warn(ds->dev,
2072751aa5a5SWei Fang 			 "Failed to restore host flood rule on port %d\n",
2073751aa5a5SWei Fang 			 port);
2074751aa5a5SWei Fang 
2075751aa5a5SWei Fang 	/* When a port leaves a VLAN-aware bridge, dsa_port_bridge_leave()
2076751aa5a5SWei Fang 	 * follows the sequence below:
2077751aa5a5SWei Fang 	 *
2078751aa5a5SWei Fang 	 * 1. dsa_port_bridge_destroy() is called to set dp->bridge to NULL.
2079751aa5a5SWei Fang 	 * 2. dsa_broadcast() is called, which eventually invokes
2080751aa5a5SWei Fang 	 *    ds->ops->port_bridge_leave()
2081751aa5a5SWei Fang 	 * 3. dsa_port_switchdev_unsync_attrs() is called, which triggers
2082751aa5a5SWei Fang 	 *    dsa_port_reset_vlan_filtering() and ultimately calls
2083751aa5a5SWei Fang 	 *    ds->ops->port_vlan_filtering() to transition the port from
2084751aa5a5SWei Fang 	 *    VLAN-aware mode to VLAN-unaware mode.
2085751aa5a5SWei Fang 	 *
2086751aa5a5SWei Fang 	 * At step 3, since dp->bridge has already been set to NULL in step 1,
2087751aa5a5SWei Fang 	 * netc_port_vlan_filtering() will detect this and skip the creation
2088751aa5a5SWei Fang 	 * of an unaware PVID entry in the VLAN filter table. Therefore, it is
2089751aa5a5SWei Fang 	 * safe to return directly here.
2090751aa5a5SWei Fang 	 */
2091751aa5a5SWei Fang 	if (br_vlan_enabled(bridge.dev))
2092751aa5a5SWei Fang 		return;
2093751aa5a5SWei Fang 
2094751aa5a5SWei Fang 	vlan_unaware_pvid = NETC_VLAN_UNAWARE_PVID(bridge.num);
2095751aa5a5SWei Fang 	/* There is no need to check the return value even if it fails.
2096751aa5a5SWei Fang 	 * Because the PVID has been set to NETC_STANDALONE_PVID, the
2097751aa5a5SWei Fang 	 * frames will not match this VLAN entry.
2098751aa5a5SWei Fang 	 */
2099751aa5a5SWei Fang 	netc_port_del_vlan_entry(np, vlan_unaware_pvid);
2100751aa5a5SWei Fang }
2101751aa5a5SWei Fang 
2102*05b5ee61SWei Fang static int netc_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
2103*05b5ee61SWei Fang {
2104*05b5ee61SWei Fang 	struct netc_switch *priv = ds->priv;
2105*05b5ee61SWei Fang 	unsigned long delay_jiffies;
2106*05b5ee61SWei Fang 
2107*05b5ee61SWei Fang 	/* The dynamic FDB entry is deleted when its activity counter reaches
2108*05b5ee61SWei Fang 	 * NETC_FDBT_AGEING_THRESH (100). Each delayed_work tick increments
2109*05b5ee61SWei Fang 	 * the counter by 1 if the entry is inactive.
2110*05b5ee61SWei Fang 	 *
2111*05b5ee61SWei Fang 	 * Therefore:
2112*05b5ee61SWei Fang 	 *   msecs (ms)    = NETC_FDBT_AGEING_THRESH * delay_ms (ms)
2113*05b5ee61SWei Fang 	 *   delay_ms      = msecs / NETC_FDBT_AGEING_THRESH
2114*05b5ee61SWei Fang 	 *   delay_jiffies = (delay_ms / 1000) * HZ
2115*05b5ee61SWei Fang 	 *                 = (msecs * HZ) / (1000 * NETC_FDBT_AGEING_THRESH)
2116*05b5ee61SWei Fang 	 *
2117*05b5ee61SWei Fang 	 * Use DIV_ROUND_CLOSEST_ULL to perform a single nearest-jiffy
2118*05b5ee61SWei Fang 	 * rounding, avoiding the two-step rounding error of the intermediate
2119*05b5ee61SWei Fang 	 * delay_ms approach.
2120*05b5ee61SWei Fang 	 *   Maximum error = +/-0.5 jiffy * 100 = +/-50000/HZ ms.
2121*05b5ee61SWei Fang 	 */
2122*05b5ee61SWei Fang 	delay_jiffies = DIV_ROUND_CLOSEST_ULL((u64)msecs * HZ,
2123*05b5ee61SWei Fang 					      1000 * NETC_FDBT_AGEING_THRESH);
2124*05b5ee61SWei Fang 	WRITE_ONCE(priv->fdbt_ageing_delay, delay_jiffies);
2125*05b5ee61SWei Fang 
2126*05b5ee61SWei Fang 	if (atomic_read(&priv->br_cnt))
2127*05b5ee61SWei Fang 		mod_delayed_work(system_percpu_wq, &priv->fdbt_ageing_work,
2128*05b5ee61SWei Fang 				 READ_ONCE(priv->fdbt_ageing_delay));
2129*05b5ee61SWei Fang 
2130*05b5ee61SWei Fang 	return 0;
2131*05b5ee61SWei Fang }
2132*05b5ee61SWei Fang 
2133751aa5a5SWei Fang static void netc_port_fast_age(struct dsa_switch *ds, int port)
2134751aa5a5SWei Fang {
2135751aa5a5SWei Fang 	struct netc_port *np = NETC_PORT(ds, port);
2136751aa5a5SWei Fang 
2137751aa5a5SWei Fang 	netc_port_remove_dynamic_entries(np);
213884b4a3b3SWei Fang }
213984b4a3b3SWei Fang 
2140bbe97e34SWei Fang static void netc_phylink_get_caps(struct dsa_switch *ds, int port,
2141bbe97e34SWei Fang 				  struct phylink_config *config)
2142bbe97e34SWei Fang {
2143bbe97e34SWei Fang 	struct netc_switch *priv = ds->priv;
2144bbe97e34SWei Fang 
2145bbe97e34SWei Fang 	priv->info->phylink_get_caps(port, config);
2146bbe97e34SWei Fang }
2147bbe97e34SWei Fang 
2148bbe97e34SWei Fang static void netc_port_set_mac_mode(struct netc_port *np,
2149bbe97e34SWei Fang 				   unsigned int mode,
2150bbe97e34SWei Fang 				   phy_interface_t phy_mode)
2151bbe97e34SWei Fang {
2152bbe97e34SWei Fang 	u32 mask = PM_IF_MODE_IFMODE | PM_IF_MODE_REVMII;
2153bbe97e34SWei Fang 	u32 val = 0;
2154bbe97e34SWei Fang 
2155bbe97e34SWei Fang 	switch (phy_mode) {
2156bbe97e34SWei Fang 	case PHY_INTERFACE_MODE_RGMII:
2157bbe97e34SWei Fang 	case PHY_INTERFACE_MODE_RGMII_ID:
2158bbe97e34SWei Fang 	case PHY_INTERFACE_MODE_RGMII_RXID:
2159bbe97e34SWei Fang 	case PHY_INTERFACE_MODE_RGMII_TXID:
2160bbe97e34SWei Fang 		val |= IFMODE_RGMII;
2161bbe97e34SWei Fang 		break;
2162bbe97e34SWei Fang 	case PHY_INTERFACE_MODE_RMII:
2163bbe97e34SWei Fang 		val |= IFMODE_RMII;
2164bbe97e34SWei Fang 		break;
2165bbe97e34SWei Fang 	case PHY_INTERFACE_MODE_REVMII:
2166bbe97e34SWei Fang 		val |= PM_IF_MODE_REVMII;
2167bbe97e34SWei Fang 		fallthrough;
2168bbe97e34SWei Fang 	case PHY_INTERFACE_MODE_MII:
2169bbe97e34SWei Fang 		val |= IFMODE_MII;
2170bbe97e34SWei Fang 		break;
2171bbe97e34SWei Fang 	case PHY_INTERFACE_MODE_SGMII:
2172bbe97e34SWei Fang 	case PHY_INTERFACE_MODE_2500BASEX:
2173bbe97e34SWei Fang 		val |= IFMODE_SGMII;
2174bbe97e34SWei Fang 		break;
2175bbe97e34SWei Fang 	default:
2176bbe97e34SWei Fang 		break;
2177bbe97e34SWei Fang 	}
2178bbe97e34SWei Fang 
2179bbe97e34SWei Fang 	netc_mac_port_rmw(np, NETC_PM_IF_MODE(0), mask, val);
2180bbe97e34SWei Fang }
2181bbe97e34SWei Fang 
2182bbe97e34SWei Fang static void netc_mac_config(struct phylink_config *config, unsigned int mode,
2183bbe97e34SWei Fang 			    const struct phylink_link_state *state)
2184bbe97e34SWei Fang {
2185bbe97e34SWei Fang 	struct dsa_port *dp = dsa_phylink_to_port(config);
2186bbe97e34SWei Fang 
2187bbe97e34SWei Fang 	netc_port_set_mac_mode(NETC_PORT(dp->ds, dp->index), mode,
2188bbe97e34SWei Fang 			       state->interface);
2189bbe97e34SWei Fang }
2190bbe97e34SWei Fang 
2191bbe97e34SWei Fang static void netc_port_set_speed(struct netc_port *np, int speed)
2192bbe97e34SWei Fang {
2193bbe97e34SWei Fang 	netc_port_rmw(np, NETC_PCR, PCR_PSPEED, PSPEED_SET_VAL(speed));
2194bbe97e34SWei Fang }
2195bbe97e34SWei Fang 
2196bbe97e34SWei Fang static void netc_port_set_rgmii_mac(struct netc_port *np,
2197bbe97e34SWei Fang 				    int speed, int duplex)
2198bbe97e34SWei Fang {
2199bbe97e34SWei Fang 	u32 mask, val;
2200bbe97e34SWei Fang 
2201bbe97e34SWei Fang 	mask = PM_IF_MODE_SSP | PM_IF_MODE_HD | PM_IF_MODE_M10;
2202bbe97e34SWei Fang 
2203bbe97e34SWei Fang 	switch (speed) {
2204bbe97e34SWei Fang 	default:
2205bbe97e34SWei Fang 	case SPEED_1000:
2206bbe97e34SWei Fang 		val = FIELD_PREP(PM_IF_MODE_SSP, SSP_1G);
2207bbe97e34SWei Fang 		break;
2208bbe97e34SWei Fang 	case SPEED_100:
2209bbe97e34SWei Fang 		val = FIELD_PREP(PM_IF_MODE_SSP, SSP_100M);
2210bbe97e34SWei Fang 		break;
2211bbe97e34SWei Fang 	case SPEED_10:
2212bbe97e34SWei Fang 		val = FIELD_PREP(PM_IF_MODE_SSP, SSP_10M);
2213bbe97e34SWei Fang 		break;
2214bbe97e34SWei Fang 	}
2215bbe97e34SWei Fang 
2216bbe97e34SWei Fang 	if (duplex != DUPLEX_FULL)
2217bbe97e34SWei Fang 		val |= PM_IF_MODE_HD;
2218bbe97e34SWei Fang 
2219bbe97e34SWei Fang 	netc_mac_port_rmw(np, NETC_PM_IF_MODE(0), mask, val);
2220bbe97e34SWei Fang }
2221bbe97e34SWei Fang 
2222bbe97e34SWei Fang static void netc_port_set_rmii_mii_mac(struct netc_port *np,
2223bbe97e34SWei Fang 				       int speed, int duplex)
2224bbe97e34SWei Fang {
2225bbe97e34SWei Fang 	u32 mask, val = 0;
2226bbe97e34SWei Fang 
2227bbe97e34SWei Fang 	mask = PM_IF_MODE_SSP | PM_IF_MODE_HD | PM_IF_MODE_M10;
2228bbe97e34SWei Fang 
2229bbe97e34SWei Fang 	if (speed == SPEED_10)
2230bbe97e34SWei Fang 		val |= PM_IF_MODE_M10;
2231bbe97e34SWei Fang 
2232bbe97e34SWei Fang 	if (duplex != DUPLEX_FULL)
2233bbe97e34SWei Fang 		val |= PM_IF_MODE_HD;
2234bbe97e34SWei Fang 
2235bbe97e34SWei Fang 	netc_mac_port_rmw(np, NETC_PM_IF_MODE(0), mask, val);
2236bbe97e34SWei Fang }
2237bbe97e34SWei Fang 
2238a5ccb7f5SWei Fang static void netc_port_set_tx_pause(struct netc_port *np, bool tx_pause)
2239a5ccb7f5SWei Fang {
2240a5ccb7f5SWei Fang 	struct netc_switch *priv = np->switch_priv;
2241a5ccb7f5SWei Fang 	int port = np->dp->index;
2242a5ccb7f5SWei Fang 	int i, j, num_bp;
2243a5ccb7f5SWei Fang 
2244a5ccb7f5SWei Fang 	num_bp = priv->num_bp / priv->info->num_ports;
2245a5ccb7f5SWei Fang 	for (i = 0, j = port * num_bp; i < num_bp; i++, j++) {
2246a5ccb7f5SWei Fang 		struct bpt_cfge_data *cfge = &priv->bpt_list[j];
2247a5ccb7f5SWei Fang 		struct bpt_cfge_data old_cfge = *cfge;
2248a5ccb7f5SWei Fang 
2249a5ccb7f5SWei Fang 		if (tx_pause) {
2250a5ccb7f5SWei Fang 			cfge->fc_on_thresh = cpu_to_le16(NETC_FC_THRESH_ON);
2251a5ccb7f5SWei Fang 			cfge->fc_off_thresh = cpu_to_le16(NETC_FC_THRESH_OFF);
2252a5ccb7f5SWei Fang 			cfge->fccfg_sbpen = FIELD_PREP(BPT_FC_CFG,
2253a5ccb7f5SWei Fang 						       BPT_FC_CFG_EN_BPFC);
2254a5ccb7f5SWei Fang 			cfge->fc_ports = cpu_to_le32(BIT(port));
2255a5ccb7f5SWei Fang 		} else {
2256a5ccb7f5SWei Fang 			cfge->fc_on_thresh = cpu_to_le16(0);
2257a5ccb7f5SWei Fang 			cfge->fc_off_thresh = cpu_to_le16(0);
2258a5ccb7f5SWei Fang 			cfge->fccfg_sbpen = 0;
2259a5ccb7f5SWei Fang 			cfge->fc_ports = cpu_to_le32(0);
2260a5ccb7f5SWei Fang 		}
2261a5ccb7f5SWei Fang 
2262a5ccb7f5SWei Fang 		if (ntmp_bpt_update_entry(&priv->ntmp, j, cfge)) {
2263a5ccb7f5SWei Fang 			*cfge = old_cfge;
2264a5ccb7f5SWei Fang 			dev_warn(priv->dev,
2265a5ccb7f5SWei Fang 				 "Failed to %s TX pause of buffer pool %d (swp%d)\n",
2266a5ccb7f5SWei Fang 				 tx_pause ? "enable" : "disable", j, port);
2267a5ccb7f5SWei Fang 		}
2268a5ccb7f5SWei Fang 	}
2269a5ccb7f5SWei Fang }
2270a5ccb7f5SWei Fang 
2271a5ccb7f5SWei Fang static void netc_port_set_rx_pause(struct netc_port *np, bool rx_pause)
2272a5ccb7f5SWei Fang {
2273a5ccb7f5SWei Fang 	netc_mac_port_rmw(np, NETC_PM_CMD_CFG(0), PM_CMD_CFG_PAUSE_IGN,
2274a5ccb7f5SWei Fang 			  rx_pause ? 0 : PM_CMD_CFG_PAUSE_IGN);
2275a5ccb7f5SWei Fang }
2276a5ccb7f5SWei Fang 
2277bbe97e34SWei Fang static void netc_port_mac_rx_enable(struct netc_port *np)
2278bbe97e34SWei Fang {
2279bbe97e34SWei Fang 	netc_port_rmw(np, NETC_POR, POR_RXDIS, 0);
2280bbe97e34SWei Fang 	netc_mac_port_rmw(np, NETC_PM_CMD_CFG(0), PM_CMD_CFG_RX_EN,
2281bbe97e34SWei Fang 			  PM_CMD_CFG_RX_EN);
2282bbe97e34SWei Fang }
2283bbe97e34SWei Fang 
2284bbe97e34SWei Fang static void netc_port_wait_rx_empty(struct netc_port *np, int mac)
2285bbe97e34SWei Fang {
2286bbe97e34SWei Fang 	u32 val;
2287bbe97e34SWei Fang 
2288bbe97e34SWei Fang 	/* PM_IEVENT_RX_EMPTY is a read-only bit, it is automatically set by
2289bbe97e34SWei Fang 	 * hardware if RX FIFO is empty and no RX packet receive in process.
2290bbe97e34SWei Fang 	 * And it is automatically cleared if RX FIFO is not empty or RX
2291bbe97e34SWei Fang 	 * packet receive in process.
2292bbe97e34SWei Fang 	 */
2293bbe97e34SWei Fang 	if (read_poll_timeout(netc_port_rd, val, val & PM_IEVENT_RX_EMPTY,
2294bbe97e34SWei Fang 			      100, 10000, false, np, NETC_PM_IEVENT(mac)))
2295bbe97e34SWei Fang 		dev_warn(np->switch_priv->dev,
2296bbe97e34SWei Fang 			 "swp%d MAC%d: RX is not idle\n", np->dp->index, mac);
2297bbe97e34SWei Fang }
2298bbe97e34SWei Fang 
2299bbe97e34SWei Fang static void netc_port_mac_rx_graceful_stop(struct netc_port *np)
2300bbe97e34SWei Fang {
2301bbe97e34SWei Fang 	u32 val;
2302bbe97e34SWei Fang 
2303bbe97e34SWei Fang 	if (is_netc_pseudo_port(np))
2304bbe97e34SWei Fang 		goto rx_disable;
2305bbe97e34SWei Fang 
2306bbe97e34SWei Fang 	if (np->caps.pmac) {
2307bbe97e34SWei Fang 		netc_port_rmw(np, NETC_PM_CMD_CFG(1), PM_CMD_CFG_RX_EN, 0);
2308bbe97e34SWei Fang 		netc_port_wait_rx_empty(np, 1);
2309bbe97e34SWei Fang 	}
2310bbe97e34SWei Fang 
2311bbe97e34SWei Fang 	netc_port_rmw(np, NETC_PM_CMD_CFG(0), PM_CMD_CFG_RX_EN, 0);
2312bbe97e34SWei Fang 	netc_port_wait_rx_empty(np, 0);
2313bbe97e34SWei Fang 
2314bbe97e34SWei Fang 	if (read_poll_timeout(netc_port_rd, val, !(val & PSR_RX_BUSY),
2315bbe97e34SWei Fang 			      100, 10000, false, np, NETC_PSR))
2316bbe97e34SWei Fang 		dev_warn(np->switch_priv->dev, "swp%d RX is busy\n",
2317bbe97e34SWei Fang 			 np->dp->index);
2318bbe97e34SWei Fang 
2319bbe97e34SWei Fang rx_disable:
2320bbe97e34SWei Fang 	netc_port_rmw(np, NETC_POR, POR_RXDIS, POR_RXDIS);
2321bbe97e34SWei Fang }
2322bbe97e34SWei Fang 
2323bbe97e34SWei Fang static void netc_port_mac_tx_enable(struct netc_port *np)
2324bbe97e34SWei Fang {
2325bbe97e34SWei Fang 	netc_mac_port_rmw(np, NETC_PM_CMD_CFG(0), PM_CMD_CFG_TX_EN,
2326bbe97e34SWei Fang 			  PM_CMD_CFG_TX_EN);
2327bbe97e34SWei Fang 	netc_port_rmw(np, NETC_POR, POR_TXDIS, 0);
2328bbe97e34SWei Fang }
2329bbe97e34SWei Fang 
2330bbe97e34SWei Fang static void netc_port_wait_tx_empty(struct netc_port *np, int mac)
2331bbe97e34SWei Fang {
2332bbe97e34SWei Fang 	u32 val;
2333bbe97e34SWei Fang 
2334bbe97e34SWei Fang 	/* PM_IEVENT_TX_EMPTY is a read-only bit, it is automatically set by
2335bbe97e34SWei Fang 	 * hardware if TX FIFO is empty. And it is automatically cleared if
2336bbe97e34SWei Fang 	 * TX FIFO is not empty.
2337bbe97e34SWei Fang 	 */
2338bbe97e34SWei Fang 	if (read_poll_timeout(netc_port_rd, val, val & PM_IEVENT_TX_EMPTY,
2339bbe97e34SWei Fang 			      100, 10000, false, np, NETC_PM_IEVENT(mac)))
2340bbe97e34SWei Fang 		dev_warn(np->switch_priv->dev,
2341bbe97e34SWei Fang 			 "swp%d MAC%d: TX FIFO is not empty\n",
2342bbe97e34SWei Fang 			 np->dp->index, mac);
2343bbe97e34SWei Fang }
2344bbe97e34SWei Fang 
2345bbe97e34SWei Fang static void netc_port_mac_tx_graceful_stop(struct netc_port *np)
2346bbe97e34SWei Fang {
2347bbe97e34SWei Fang 	netc_port_rmw(np, NETC_POR, POR_TXDIS, POR_TXDIS);
2348bbe97e34SWei Fang 
2349bbe97e34SWei Fang 	if (is_netc_pseudo_port(np))
2350bbe97e34SWei Fang 		return;
2351bbe97e34SWei Fang 
2352bbe97e34SWei Fang 	netc_port_wait_tx_empty(np, 0);
2353bbe97e34SWei Fang 	if (np->caps.pmac)
2354bbe97e34SWei Fang 		netc_port_wait_tx_empty(np, 1);
2355bbe97e34SWei Fang 
2356bbe97e34SWei Fang 	netc_mac_port_rmw(np, NETC_PM_CMD_CFG(0), PM_CMD_CFG_TX_EN, 0);
2357bbe97e34SWei Fang }
2358bbe97e34SWei Fang 
2359bbe97e34SWei Fang static void netc_mac_link_up(struct phylink_config *config,
2360bbe97e34SWei Fang 			     struct phy_device *phy, unsigned int mode,
2361bbe97e34SWei Fang 			     phy_interface_t interface, int speed,
2362bbe97e34SWei Fang 			     int duplex, bool tx_pause, bool rx_pause)
2363bbe97e34SWei Fang {
2364bbe97e34SWei Fang 	struct dsa_port *dp = dsa_phylink_to_port(config);
2365bbe97e34SWei Fang 	struct netc_port *np;
2366bbe97e34SWei Fang 
2367bbe97e34SWei Fang 	np = NETC_PORT(dp->ds, dp->index);
2368bbe97e34SWei Fang 	netc_port_set_speed(np, speed);
2369bbe97e34SWei Fang 
2370bbe97e34SWei Fang 	if (phy_interface_mode_is_rgmii(interface))
2371bbe97e34SWei Fang 		netc_port_set_rgmii_mac(np, speed, duplex);
2372bbe97e34SWei Fang 
2373bbe97e34SWei Fang 	if (interface == PHY_INTERFACE_MODE_RMII ||
2374bbe97e34SWei Fang 	    interface == PHY_INTERFACE_MODE_REVMII ||
2375bbe97e34SWei Fang 	    interface == PHY_INTERFACE_MODE_MII)
2376bbe97e34SWei Fang 		netc_port_set_rmii_mii_mac(np, speed, duplex);
2377bbe97e34SWei Fang 
2378a5ccb7f5SWei Fang 	netc_port_set_tx_pause(np, tx_pause);
2379a5ccb7f5SWei Fang 	netc_port_set_rx_pause(np, rx_pause);
2380bbe97e34SWei Fang 	netc_port_mac_tx_enable(np);
2381bbe97e34SWei Fang 	netc_port_mac_rx_enable(np);
2382bbe97e34SWei Fang }
2383bbe97e34SWei Fang 
2384bbe97e34SWei Fang static void netc_mac_link_down(struct phylink_config *config,
2385bbe97e34SWei Fang 			       unsigned int mode,
2386bbe97e34SWei Fang 			       phy_interface_t interface)
2387bbe97e34SWei Fang {
2388bbe97e34SWei Fang 	struct dsa_port *dp = dsa_phylink_to_port(config);
2389bbe97e34SWei Fang 	struct netc_port *np;
2390bbe97e34SWei Fang 
2391bbe97e34SWei Fang 	np = NETC_PORT(dp->ds, dp->index);
2392bbe97e34SWei Fang 	netc_port_mac_rx_graceful_stop(np);
2393bbe97e34SWei Fang 	netc_port_mac_tx_graceful_stop(np);
2394751aa5a5SWei Fang 	netc_port_remove_dynamic_entries(np);
2395bbe97e34SWei Fang }
2396bbe97e34SWei Fang 
2397bbe97e34SWei Fang static const struct phylink_mac_ops netc_phylink_mac_ops = {
2398bbe97e34SWei Fang 	.mac_config		= netc_mac_config,
2399bbe97e34SWei Fang 	.mac_link_up		= netc_mac_link_up,
2400bbe97e34SWei Fang 	.mac_link_down		= netc_mac_link_down,
2401bbe97e34SWei Fang };
2402bbe97e34SWei Fang 
2403187fbae0SWei Fang static const struct dsa_switch_ops netc_switch_ops = {
2404187fbae0SWei Fang 	.get_tag_protocol		= netc_get_tag_protocol,
2405187fbae0SWei Fang 	.setup				= netc_setup,
2406187fbae0SWei Fang 	.teardown			= netc_teardown,
2407bbe97e34SWei Fang 	.phylink_get_caps		= netc_phylink_get_caps,
240846d64076SWei Fang 	.port_enable			= netc_port_enable,
240946d64076SWei Fang 	.port_disable			= netc_port_disable,
241046d64076SWei Fang 	.port_stp_state_set		= netc_port_stp_state_set,
241146d64076SWei Fang 	.port_change_mtu		= netc_port_change_mtu,
241246d64076SWei Fang 	.port_max_mtu			= netc_port_max_mtu,
241346d64076SWei Fang 	.port_fdb_add			= netc_port_fdb_add,
241446d64076SWei Fang 	.port_fdb_del			= netc_port_fdb_del,
241546d64076SWei Fang 	.port_fdb_dump			= netc_port_fdb_dump,
241646d64076SWei Fang 	.port_mdb_add			= netc_port_mdb_add,
241746d64076SWei Fang 	.port_mdb_del			= netc_port_mdb_del,
241846d64076SWei Fang 	.port_set_host_flood		= netc_port_set_host_flood,
2419751aa5a5SWei Fang 	.port_vlan_filtering		= netc_port_vlan_filtering,
242084b4a3b3SWei Fang 	.port_vlan_add			= netc_port_vlan_add,
242184b4a3b3SWei Fang 	.port_vlan_del			= netc_port_vlan_del,
2422751aa5a5SWei Fang 	.port_bridge_join		= netc_port_bridge_join,
2423751aa5a5SWei Fang 	.port_bridge_leave		= netc_port_bridge_leave,
2424*05b5ee61SWei Fang 	.set_ageing_time		= netc_set_ageing_time,
2425751aa5a5SWei Fang 	.port_fast_age			= netc_port_fast_age,
242625049d8bSWei Fang 	.get_pause_stats		= netc_port_get_pause_stats,
242725049d8bSWei Fang 	.get_rmon_stats			= netc_port_get_rmon_stats,
242825049d8bSWei Fang 	.get_eth_ctrl_stats		= netc_port_get_eth_ctrl_stats,
242925049d8bSWei Fang 	.get_eth_mac_stats		= netc_port_get_eth_mac_stats,
2430beb0e54fSWei Fang 	.get_sset_count			= netc_port_get_sset_count,
2431beb0e54fSWei Fang 	.get_strings			= netc_port_get_strings,
2432beb0e54fSWei Fang 	.get_ethtool_stats		= netc_port_get_ethtool_stats,
2433187fbae0SWei Fang };
2434187fbae0SWei Fang 
2435187fbae0SWei Fang static int netc_switch_probe(struct pci_dev *pdev,
2436187fbae0SWei Fang 			     const struct pci_device_id *id)
2437187fbae0SWei Fang {
2438187fbae0SWei Fang 	struct device_node *node = dev_of_node(&pdev->dev);
2439187fbae0SWei Fang 	struct device *dev = &pdev->dev;
2440187fbae0SWei Fang 	struct netc_switch *priv;
2441187fbae0SWei Fang 	struct dsa_switch *ds;
2442187fbae0SWei Fang 	int err;
2443187fbae0SWei Fang 
2444187fbae0SWei Fang 	if (!node)
2445187fbae0SWei Fang 		return dev_err_probe(dev, -ENODEV,
2446187fbae0SWei Fang 				     "No DT bindings, skipping\n");
2447187fbae0SWei Fang 
2448187fbae0SWei Fang 	err = netc_switch_check_emdio_is_ready(dev);
2449187fbae0SWei Fang 	if (err)
2450187fbae0SWei Fang 		return err;
2451187fbae0SWei Fang 
2452187fbae0SWei Fang 	err = netc_switch_pci_init(pdev);
2453187fbae0SWei Fang 	if (err)
2454187fbae0SWei Fang 		return err;
2455187fbae0SWei Fang 
2456187fbae0SWei Fang 	priv = pci_get_drvdata(pdev);
2457187fbae0SWei Fang 	netc_switch_get_ip_revision(priv);
2458187fbae0SWei Fang 
2459187fbae0SWei Fang 	err = netc_switch_platform_probe(priv);
2460187fbae0SWei Fang 	if (err)
2461187fbae0SWei Fang 		return err;
2462187fbae0SWei Fang 
2463187fbae0SWei Fang 	ds = devm_kzalloc(dev, sizeof(*ds), GFP_KERNEL);
2464187fbae0SWei Fang 	if (!ds)
2465187fbae0SWei Fang 		return -ENOMEM;
2466187fbae0SWei Fang 
2467187fbae0SWei Fang 	ds->dev = dev;
2468187fbae0SWei Fang 	ds->num_ports = priv->info->num_ports;
2469187fbae0SWei Fang 	ds->num_tx_queues = NETC_TC_NUM;
2470187fbae0SWei Fang 	ds->ops = &netc_switch_ops;
2471bbe97e34SWei Fang 	ds->phylink_mac_ops = &netc_phylink_mac_ops;
247246d64076SWei Fang 	ds->fdb_isolation = true;
2473751aa5a5SWei Fang 	ds->max_num_bridges = priv->info->num_ports - 1;
2474*05b5ee61SWei Fang 	ds->ageing_time_min = 1000;
2475*05b5ee61SWei Fang 	ds->ageing_time_max = U32_MAX;
2476187fbae0SWei Fang 	ds->priv = priv;
2477187fbae0SWei Fang 	priv->ds = ds;
2478187fbae0SWei Fang 
2479187fbae0SWei Fang 	err = dsa_register_switch(ds);
2480187fbae0SWei Fang 	if (err)
2481187fbae0SWei Fang 		return dev_err_probe(dev, err,
2482187fbae0SWei Fang 				     "Failed to register DSA switch\n");
2483187fbae0SWei Fang 
2484187fbae0SWei Fang 	return 0;
2485187fbae0SWei Fang }
2486187fbae0SWei Fang 
2487187fbae0SWei Fang static void netc_switch_remove(struct pci_dev *pdev)
2488187fbae0SWei Fang {
2489187fbae0SWei Fang 	struct netc_switch *priv = pci_get_drvdata(pdev);
2490187fbae0SWei Fang 
2491187fbae0SWei Fang 	if (!priv)
2492187fbae0SWei Fang 		return;
2493187fbae0SWei Fang 
2494187fbae0SWei Fang 	dsa_unregister_switch(priv->ds);
2495187fbae0SWei Fang }
2496187fbae0SWei Fang 
2497187fbae0SWei Fang static void netc_switch_shutdown(struct pci_dev *pdev)
2498187fbae0SWei Fang {
2499187fbae0SWei Fang 	struct netc_switch *priv = pci_get_drvdata(pdev);
2500187fbae0SWei Fang 
2501187fbae0SWei Fang 	if (!priv)
2502187fbae0SWei Fang 		return;
2503187fbae0SWei Fang 
2504187fbae0SWei Fang 	dsa_switch_shutdown(priv->ds);
2505187fbae0SWei Fang 	pci_set_drvdata(pdev, NULL);
2506187fbae0SWei Fang }
2507187fbae0SWei Fang 
2508187fbae0SWei Fang static const struct pci_device_id netc_switch_ids[] = {
2509187fbae0SWei Fang 	{ PCI_DEVICE(NETC_SWITCH_VENDOR_ID, NETC_SWITCH_DEVICE_ID) },
2510187fbae0SWei Fang 	{ }
2511187fbae0SWei Fang };
2512187fbae0SWei Fang MODULE_DEVICE_TABLE(pci, netc_switch_ids);
2513187fbae0SWei Fang 
2514187fbae0SWei Fang static struct pci_driver netc_switch_driver = {
2515187fbae0SWei Fang 	.name		= KBUILD_MODNAME,
2516187fbae0SWei Fang 	.id_table	= netc_switch_ids,
2517187fbae0SWei Fang 	.probe		= netc_switch_probe,
2518187fbae0SWei Fang 	.remove		= netc_switch_remove,
2519187fbae0SWei Fang 	.shutdown	= netc_switch_shutdown,
2520187fbae0SWei Fang };
2521187fbae0SWei Fang module_pci_driver(netc_switch_driver);
2522187fbae0SWei Fang 
2523187fbae0SWei Fang MODULE_DESCRIPTION("NXP NETC Switch driver");
2524187fbae0SWei Fang MODULE_LICENSE("Dual BSD/GPL");
2525