xref: /linux/drivers/net/ethernet/airoha/airoha_ppe.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2025 AIROHA Inc
4  * Author: Lorenzo Bianconi <lorenzo@kernel.org>
5  */
6 
7 #include <linux/ip.h>
8 #include <linux/ipv6.h>
9 #include <linux/of_platform.h>
10 #include <linux/platform_device.h>
11 #include <linux/rhashtable.h>
12 #include <net/ipv6.h>
13 #include <net/pkt_cls.h>
14 
15 #include "airoha_regs.h"
16 #include "airoha_eth.h"
17 
18 /* Serialize airoha_gdm_dev flags, QDMA pointer and PPE CPU port
19  * configuration.
20  */
21 DEFINE_MUTEX(flow_offload_mutex);
22 static DEFINE_SPINLOCK(ppe_lock);
23 
24 static const struct rhashtable_params airoha_flow_table_params = {
25 	.head_offset = offsetof(struct airoha_flow_table_entry, node),
26 	.key_offset = offsetof(struct airoha_flow_table_entry, cookie),
27 	.key_len = sizeof(unsigned long),
28 	.automatic_shrinking = true,
29 };
30 
31 static const struct rhashtable_params airoha_l2_flow_table_params = {
32 	.head_offset = offsetof(struct airoha_flow_table_entry, l2_node),
33 	.key_offset = offsetof(struct airoha_flow_table_entry, data.bridge),
34 	.key_len = 2 * ETH_ALEN,
35 	.automatic_shrinking = true,
36 };
37 
airoha_ppe_get_num_stats_entries(struct airoha_ppe * ppe)38 static int airoha_ppe_get_num_stats_entries(struct airoha_ppe *ppe)
39 {
40 	if (!IS_ENABLED(CONFIG_NET_AIROHA_FLOW_STATS))
41 		return -EOPNOTSUPP;
42 
43 	if (airoha_is_7583(ppe->eth))
44 		return -EOPNOTSUPP;
45 
46 	return PPE_STATS_NUM_ENTRIES;
47 }
48 
airoha_ppe_get_total_num_stats_entries(struct airoha_ppe * ppe)49 static int airoha_ppe_get_total_num_stats_entries(struct airoha_ppe *ppe)
50 {
51 	int num_stats = airoha_ppe_get_num_stats_entries(ppe);
52 
53 	if (num_stats > 0) {
54 		struct airoha_eth *eth = ppe->eth;
55 
56 		num_stats = num_stats * eth->soc->num_ppe;
57 	}
58 
59 	return num_stats;
60 }
61 
airoha_ppe_get_total_sram_num_entries(struct airoha_ppe * ppe)62 static u32 airoha_ppe_get_total_sram_num_entries(struct airoha_ppe *ppe)
63 {
64 	struct airoha_eth *eth = ppe->eth;
65 
66 	return PPE_SRAM_NUM_ENTRIES * eth->soc->num_ppe;
67 }
68 
airoha_ppe_get_total_num_entries(struct airoha_ppe * ppe)69 u32 airoha_ppe_get_total_num_entries(struct airoha_ppe *ppe)
70 {
71 	u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe);
72 
73 	return sram_num_entries + PPE_DRAM_NUM_ENTRIES;
74 }
75 
airoha_ppe_is_enabled(struct airoha_eth * eth,int index)76 bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index)
77 {
78 	if (index >= eth->soc->num_ppe)
79 		return false;
80 
81 	return airoha_fe_rr(eth, REG_PPE_GLO_CFG(index)) & PPE_GLO_CFG_EN_MASK;
82 }
83 
airoha_ppe_get_timestamp(struct airoha_ppe * ppe)84 static u32 airoha_ppe_get_timestamp(struct airoha_ppe *ppe)
85 {
86 	return airoha_fe_get(ppe->eth, REG_FE_FOE_TS,
87 			     AIROHA_FOE_IB1_BIND_TIMESTAMP);
88 }
89 
airoha_ppe_set_cpu_port(struct airoha_gdm_dev * dev,u8 ppe_id,u8 fport)90 void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport)
91 {
92 	struct airoha_qdma *qdma = airoha_qdma_deref(dev);
93 	struct airoha_eth *eth = dev->eth;
94 	u8 qdma_id = qdma - &eth->qdma[0];
95 	u32 fe_cpu_port;
96 
97 	fe_cpu_port = qdma_id ? FE_PSE_PORT_CDM2 : FE_PSE_PORT_CDM1;
98 	airoha_fe_rmw(eth, REG_PPE_DFT_CPORT(ppe_id, fport),
99 		      DFT_CPORT_MASK(fport),
100 		      __field_prep(DFT_CPORT_MASK(fport), fe_cpu_port));
101 }
102 
airoha_ppe_set_xmit_frame_size(struct airoha_gdm_dev * dev)103 void airoha_ppe_set_xmit_frame_size(struct airoha_gdm_dev *dev)
104 {
105 	struct airoha_gdm_port *port = dev->port;
106 	struct airoha_eth *eth = dev->eth;
107 	int i, ppe_id, index;
108 	u32 len = 0;
109 
110 	for (i = 0; i < ARRAY_SIZE(port->devs); i++) {
111 		struct airoha_gdm_dev *d = port->devs[i];
112 		struct net_device *netdev;
113 
114 		if (!d)
115 			continue;
116 
117 		netdev = netdev_from_priv(d);
118 		if (netif_running(netdev))
119 			len = max_t(u32, len, netdev->mtu);
120 	}
121 	len += VLAN_ETH_HLEN;
122 
123 	ppe_id = !airoha_is_lan_gdm_dev(dev) && airoha_ppe_is_enabled(eth, 1);
124 	index = port->id == AIROHA_GDM4_IDX ? 7 : port->id;
125 	airoha_fe_rmw(eth, REG_PPE_MTU(ppe_id, index),
126 		      FP_EGRESS_MTU_MASK(index),
127 		      __field_prep(FP_EGRESS_MTU_MASK(index), len));
128 }
129 
airoha_ppe_hw_init(struct airoha_ppe * ppe)130 static void airoha_ppe_hw_init(struct airoha_ppe *ppe)
131 {
132 	u32 sram_ppe_num_data_entries = PPE_SRAM_NUM_ENTRIES, sram_num_entries;
133 	u32 sram_tb_size, dram_num_entries;
134 	struct airoha_eth *eth = ppe->eth;
135 	int i, sram_num_stats_entries;
136 
137 	sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe);
138 	sram_tb_size = sram_num_entries * sizeof(struct airoha_foe_entry);
139 	dram_num_entries = PPE_RAM_NUM_ENTRIES_SHIFT(PPE_DRAM_NUM_ENTRIES);
140 
141 	sram_num_stats_entries = airoha_ppe_get_num_stats_entries(ppe);
142 	if (sram_num_stats_entries > 0)
143 		sram_ppe_num_data_entries -= sram_num_stats_entries;
144 	sram_ppe_num_data_entries =
145 		PPE_RAM_NUM_ENTRIES_SHIFT(sram_ppe_num_data_entries);
146 
147 	for (i = 0; i < eth->soc->num_ppe; i++) {
148 		airoha_fe_wr(eth, REG_PPE_TB_BASE(i),
149 			     ppe->foe_dma + sram_tb_size);
150 
151 		airoha_fe_rmw(eth, REG_PPE_BND_AGE0(i),
152 			      PPE_BIND_AGE0_DELTA_NON_L4 |
153 			      PPE_BIND_AGE0_DELTA_UDP,
154 			      FIELD_PREP(PPE_BIND_AGE0_DELTA_NON_L4, 60) |
155 			      FIELD_PREP(PPE_BIND_AGE0_DELTA_UDP, 60));
156 		airoha_fe_rmw(eth, REG_PPE_BND_AGE1(i),
157 			      PPE_BIND_AGE1_DELTA_TCP_FIN |
158 			      PPE_BIND_AGE1_DELTA_TCP,
159 			      FIELD_PREP(PPE_BIND_AGE1_DELTA_TCP_FIN, 1) |
160 			      FIELD_PREP(PPE_BIND_AGE1_DELTA_TCP, 60));
161 
162 		airoha_fe_rmw(eth, REG_PPE_TB_HASH_CFG(i),
163 			      PPE_SRAM_TABLE_EN_MASK |
164 			      PPE_SRAM_HASH1_EN_MASK |
165 			      PPE_DRAM_TABLE_EN_MASK |
166 			      PPE_SRAM_HASH0_MODE_MASK |
167 			      PPE_SRAM_HASH1_MODE_MASK |
168 			      PPE_DRAM_HASH0_MODE_MASK |
169 			      PPE_DRAM_HASH1_MODE_MASK,
170 			      FIELD_PREP(PPE_SRAM_TABLE_EN_MASK, 1) |
171 			      FIELD_PREP(PPE_SRAM_HASH1_EN_MASK, 1) |
172 			      FIELD_PREP(PPE_SRAM_HASH1_MODE_MASK, 1) |
173 			      FIELD_PREP(PPE_DRAM_HASH1_MODE_MASK, 3));
174 
175 		airoha_fe_rmw(eth, REG_PPE_TB_CFG(i),
176 			      PPE_TB_CFG_SEARCH_MISS_MASK |
177 			      PPE_SRAM_TB_NUM_ENTRY_MASK |
178 			      PPE_DRAM_TB_NUM_ENTRY_MASK |
179 			      PPE_TB_CFG_KEEPALIVE_MASK |
180 			      PPE_TB_ENTRY_SIZE_MASK,
181 			      FIELD_PREP(PPE_TB_CFG_SEARCH_MISS_MASK, 3) |
182 			      FIELD_PREP(PPE_TB_ENTRY_SIZE_MASK, 0) |
183 			      FIELD_PREP(PPE_SRAM_TB_NUM_ENTRY_MASK,
184 					 sram_ppe_num_data_entries) |
185 			      FIELD_PREP(PPE_DRAM_TB_NUM_ENTRY_MASK,
186 					 dram_num_entries));
187 
188 		airoha_fe_rmw(eth, REG_PPE_BIND_RATE(i),
189 			      PPE_BIND_RATE_L2B_BIND_MASK |
190 			      PPE_BIND_RATE_BIND_MASK,
191 			      FIELD_PREP(PPE_BIND_RATE_L2B_BIND_MASK, 0x1e) |
192 			      FIELD_PREP(PPE_BIND_RATE_BIND_MASK, 0x1e));
193 
194 		airoha_fe_wr(eth, REG_PPE_HASH_SEED(i), PPE_HASH_SEED);
195 		airoha_fe_clear(eth, REG_PPE_PPE_FLOW_CFG(i),
196 				PPE_FLOW_CFG_IP6_6RD_MASK);
197 	}
198 
199 	for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
200 		struct airoha_gdm_port *port = eth->ports[i];
201 		int j;
202 
203 		if (!port)
204 			continue;
205 
206 		for (j = 0; j < ARRAY_SIZE(port->devs); j++) {
207 			struct airoha_gdm_dev *dev = port->devs[j];
208 			int ppe_id;
209 			u8 fport;
210 
211 			if (!dev)
212 				continue;
213 
214 			ppe_id = !airoha_is_lan_gdm_dev(dev) &&
215 				 airoha_ppe_is_enabled(eth, 1);
216 			fport = airoha_get_fe_port(dev);
217 			airoha_ppe_set_cpu_port(dev, ppe_id, fport);
218 			airoha_ppe_set_xmit_frame_size(dev);
219 		}
220 	}
221 }
222 
airoha_ppe_flow_mangle_eth(const struct flow_action_entry * act,void * eth)223 static void airoha_ppe_flow_mangle_eth(const struct flow_action_entry *act, void *eth)
224 {
225 	void *dest = eth + act->mangle.offset;
226 	const void *src = &act->mangle.val;
227 
228 	if (act->mangle.offset > 8)
229 		return;
230 
231 	if (act->mangle.mask == 0xffff) {
232 		src += 2;
233 		dest += 2;
234 	}
235 
236 	memcpy(dest, src, act->mangle.mask ? 2 : 4);
237 }
238 
airoha_ppe_flow_mangle_ports(const struct flow_action_entry * act,struct airoha_flow_data * data)239 static int airoha_ppe_flow_mangle_ports(const struct flow_action_entry *act,
240 					struct airoha_flow_data *data)
241 {
242 	u32 val = be32_to_cpu((__force __be32)act->mangle.val);
243 
244 	switch (act->mangle.offset) {
245 	case 0:
246 		if ((__force __be32)act->mangle.mask == ~cpu_to_be32(0xffff))
247 			data->dst_port = cpu_to_be16(val);
248 		else
249 			data->src_port = cpu_to_be16(val >> 16);
250 		break;
251 	case 2:
252 		data->dst_port = cpu_to_be16(val);
253 		break;
254 	default:
255 		return -EINVAL;
256 	}
257 
258 	return 0;
259 }
260 
airoha_ppe_flow_mangle_ipv4(const struct flow_action_entry * act,struct airoha_flow_data * data)261 static int airoha_ppe_flow_mangle_ipv4(const struct flow_action_entry *act,
262 				       struct airoha_flow_data *data)
263 {
264 	__be32 *dest;
265 
266 	switch (act->mangle.offset) {
267 	case offsetof(struct iphdr, saddr):
268 		dest = &data->v4.src_addr;
269 		break;
270 	case offsetof(struct iphdr, daddr):
271 		dest = &data->v4.dst_addr;
272 		break;
273 	default:
274 		return -EINVAL;
275 	}
276 
277 	memcpy(dest, &act->mangle.val, sizeof(u32));
278 
279 	return 0;
280 }
281 
airoha_ppe_get_wdma_info(struct net_device * dev,const u8 * addr,struct airoha_wdma_info * info)282 static int airoha_ppe_get_wdma_info(struct net_device *dev, const u8 *addr,
283 				    struct airoha_wdma_info *info)
284 {
285 	struct net_device_path_stack stack;
286 	struct net_device_path_ctx ctx = {
287 		.dev = dev,
288 	};
289 	struct net_device_path *path;
290 	int err;
291 
292 	if (!dev)
293 		return -ENODEV;
294 
295 	ether_addr_copy(ctx.daddr, addr);
296 
297 	rcu_read_lock();
298 	err = dev_fill_forward_path(&ctx, &stack);
299 	rcu_read_unlock();
300 	if (err)
301 		return err;
302 
303 	path = &stack.path[stack.num_paths - 1];
304 	if (path->type != DEV_PATH_MTK_WDMA) {
305 		err = -EINVAL;
306 		goto err_out;
307 	}
308 
309 	info->idx = path->mtk_wdma.wdma_idx;
310 	info->bss = path->mtk_wdma.bss;
311 	info->wcid = path->mtk_wdma.wcid;
312 err_out:
313 	dev_fill_forward_path_release(&stack);
314 
315 	return err;
316 }
317 
airoha_get_dsa_port(struct net_device ** dev)318 static int airoha_get_dsa_port(struct net_device **dev)
319 {
320 #if IS_ENABLED(CONFIG_NET_DSA)
321 	struct dsa_port *dp = dsa_port_from_netdev(*dev);
322 
323 	if (IS_ERR(dp))
324 		return -ENODEV;
325 
326 	*dev = dsa_port_to_conduit(dp);
327 	return dp->index;
328 #else
329 	return -ENODEV;
330 #endif
331 }
332 
airoha_ppe_foe_set_bridge_addrs(struct airoha_foe_bridge * br,struct ethhdr * eh)333 static void airoha_ppe_foe_set_bridge_addrs(struct airoha_foe_bridge *br,
334 					    struct ethhdr *eh)
335 {
336 	br->dest_mac_hi = get_unaligned_be32(eh->h_dest);
337 	br->dest_mac_lo = get_unaligned_be16(eh->h_dest + 4);
338 	br->src_mac_hi = get_unaligned_be16(eh->h_source);
339 	br->src_mac_lo = get_unaligned_be32(eh->h_source + 2);
340 }
341 
airoha_ppe_foe_entry_prepare(struct airoha_eth * eth,struct airoha_foe_entry * hwe,struct net_device * netdev,int type,struct airoha_flow_data * data,int l4proto,u8 priority)342 static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
343 					struct airoha_foe_entry *hwe,
344 					struct net_device *netdev, int type,
345 					struct airoha_flow_data *data,
346 					int l4proto, u8 priority)
347 {
348 	u32 qdata = FIELD_PREP(AIROHA_FOE_SHAPER_ID, 0x7f), ports_pad, val;
349 	int wlan_etype = -EINVAL, dsa_port = airoha_get_dsa_port(&netdev);
350 	struct airoha_foe_mac_info_common *l2;
351 	u8 smac_id = 0xf;
352 
353 	memset(hwe, 0, sizeof(*hwe));
354 
355 	val = FIELD_PREP(AIROHA_FOE_IB1_BIND_STATE, AIROHA_FOE_STATE_BIND) |
356 	      FIELD_PREP(AIROHA_FOE_IB1_BIND_PACKET_TYPE, type) |
357 	      FIELD_PREP(AIROHA_FOE_IB1_BIND_UDP, l4proto == IPPROTO_UDP) |
358 	      FIELD_PREP(AIROHA_FOE_IB1_BIND_VLAN_LAYER, data->vlan.num) |
359 	      FIELD_PREP(AIROHA_FOE_IB1_BIND_VPM, data->vlan.num) |
360 	      FIELD_PREP(AIROHA_FOE_IB1_BIND_PPPOE, data->pppoe.num) |
361 	      AIROHA_FOE_IB1_BIND_TTL;
362 	hwe->ib1 = val;
363 
364 	val = FIELD_PREP(AIROHA_FOE_IB2_PORT_AG, 0x1f);
365 	if (netdev) {
366 		struct airoha_wdma_info info = {};
367 
368 		if (!airoha_ppe_get_wdma_info(netdev, data->eth.h_dest,
369 					      &info)) {
370 			val |= FIELD_PREP(AIROHA_FOE_IB2_NBQ, info.idx) |
371 			       FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT,
372 					  FE_PSE_PORT_CDM4);
373 			qdata |= FIELD_PREP(AIROHA_FOE_ACTDP, info.bss);
374 			wlan_etype = FIELD_PREP(AIROHA_FOE_MAC_WDMA_BAND,
375 						info.idx) |
376 				     FIELD_PREP(AIROHA_FOE_MAC_WDMA_WCID,
377 						info.wcid);
378 		} else {
379 			struct airoha_gdm_dev *dev = netdev_priv(netdev);
380 			struct airoha_gdm_port *port;
381 			u8 pse_port, channel;
382 
383 			if (!airoha_is_valid_gdm_dev(eth, dev))
384 				return -EINVAL;
385 
386 			port = dev->port;
387 			if (dsa_port >= 0 || airoha_is_lan_gdm_dev(dev))
388 				pse_port = port->id == 4 ? FE_PSE_PORT_GDM4
389 							 : port->id;
390 			else
391 				pse_port = 2; /* uplink relies on GDM2
392 					       * loopback
393 					       */
394 
395 			/* For traffic forwarded to DSA devices select QoS
396 			 * channel according to the DSA user port index, rely
397 			 * on port id otherwise.
398 			 */
399 			channel = dsa_port >= 0 ? dsa_port : port->id;
400 			channel = channel % AIROHA_NUM_QOS_CHANNELS;
401 			priority = priority % AIROHA_NUM_QOS_QUEUES;
402 			qdata |= FIELD_PREP(AIROHA_FOE_CHANNEL, channel) |
403 				 FIELD_PREP(AIROHA_FOE_QID, priority);
404 
405 			val |= FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT, pse_port) |
406 			       AIROHA_FOE_IB2_PSE_QOS;
407 			/* For downlink traffic consume SRAM memory for hw
408 			 * forwarding descriptors queue.
409 			 */
410 			if (airoha_is_lan_gdm_dev(dev))
411 				val |= AIROHA_FOE_IB2_FAST_PATH;
412 			if (dsa_port >= 0)
413 				val |= FIELD_PREP(AIROHA_FOE_IB2_NBQ,
414 						  dsa_port);
415 
416 			smac_id = port->id;
417 		}
418 	}
419 
420 	if (is_multicast_ether_addr(data->eth.h_dest))
421 		val |= AIROHA_FOE_IB2_MULTICAST;
422 
423 	ports_pad = 0xa5a5a500 | (l4proto & 0xff);
424 	if (type == PPE_PKT_TYPE_IPV4_ROUTE)
425 		hwe->ipv4.orig_tuple.ports = ports_pad;
426 	if (type == PPE_PKT_TYPE_IPV6_ROUTE_3T)
427 		hwe->ipv6.ports = ports_pad;
428 
429 	if (type == PPE_PKT_TYPE_BRIDGE) {
430 		airoha_ppe_foe_set_bridge_addrs(&hwe->bridge, &data->eth);
431 		hwe->bridge.data = qdata;
432 		hwe->bridge.ib2 = val;
433 		l2 = &hwe->bridge.l2.common;
434 	} else if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) {
435 		hwe->ipv6.data = qdata;
436 		hwe->ipv6.ib2 = val;
437 		l2 = &hwe->ipv6.l2;
438 		l2->etype = ETH_P_IPV6;
439 	} else {
440 		hwe->ipv4.data = qdata;
441 		hwe->ipv4.ib2 = val;
442 		l2 = &hwe->ipv4.l2.common;
443 		l2->etype = ETH_P_IP;
444 	}
445 
446 	l2->dest_mac_hi = get_unaligned_be32(data->eth.h_dest);
447 	l2->dest_mac_lo = get_unaligned_be16(data->eth.h_dest + 4);
448 	if (type <= PPE_PKT_TYPE_IPV4_DSLITE) {
449 		struct airoha_foe_mac_info *mac_info;
450 
451 		l2->src_mac_hi = get_unaligned_be32(data->eth.h_source);
452 		hwe->ipv4.l2.src_mac_lo =
453 			get_unaligned_be16(data->eth.h_source + 4);
454 
455 		mac_info = (struct airoha_foe_mac_info *)l2;
456 		mac_info->pppoe_id = data->pppoe.sid;
457 	} else {
458 		l2->src_mac_hi = FIELD_PREP(AIROHA_FOE_MAC_SMAC_ID, smac_id) |
459 				 FIELD_PREP(AIROHA_FOE_MAC_PPPOE_ID,
460 					    data->pppoe.sid);
461 	}
462 
463 	if (data->vlan.num) {
464 		l2->vlan1 = data->vlan.hdr[0].id;
465 		if (data->vlan.num == 2)
466 			l2->vlan2 = data->vlan.hdr[1].id;
467 	}
468 
469 	if (wlan_etype >= 0) {
470 		l2->etype = wlan_etype;
471 	} else if (dsa_port >= 0) {
472 		l2->etype = BIT(dsa_port);
473 		l2->etype |= !data->vlan.num ? BIT(15) : 0;
474 	} else if (data->pppoe.num) {
475 		l2->etype = ETH_P_PPP_SES;
476 	}
477 
478 	return 0;
479 }
480 
airoha_ppe_foe_entry_set_ipv4_tuple(struct airoha_foe_entry * hwe,struct airoha_flow_data * data,bool egress)481 static int airoha_ppe_foe_entry_set_ipv4_tuple(struct airoha_foe_entry *hwe,
482 					       struct airoha_flow_data *data,
483 					       bool egress)
484 {
485 	int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1);
486 	struct airoha_foe_ipv4_tuple *t;
487 
488 	switch (type) {
489 	case PPE_PKT_TYPE_IPV4_HNAPT:
490 		if (egress) {
491 			t = &hwe->ipv4.new_tuple;
492 			break;
493 		}
494 		fallthrough;
495 	case PPE_PKT_TYPE_IPV4_DSLITE:
496 	case PPE_PKT_TYPE_IPV4_ROUTE:
497 		t = &hwe->ipv4.orig_tuple;
498 		break;
499 	default:
500 		WARN_ON_ONCE(1);
501 		return -EINVAL;
502 	}
503 
504 	t->src_ip = be32_to_cpu(data->v4.src_addr);
505 	t->dest_ip = be32_to_cpu(data->v4.dst_addr);
506 
507 	if (type != PPE_PKT_TYPE_IPV4_ROUTE) {
508 		t->src_port = be16_to_cpu(data->src_port);
509 		t->dest_port = be16_to_cpu(data->dst_port);
510 	}
511 
512 	return 0;
513 }
514 
airoha_ppe_foe_entry_set_ipv6_tuple(struct airoha_foe_entry * hwe,struct airoha_flow_data * data)515 static int airoha_ppe_foe_entry_set_ipv6_tuple(struct airoha_foe_entry *hwe,
516 					       struct airoha_flow_data *data)
517 
518 {
519 	int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1);
520 	u32 *src, *dest;
521 
522 	switch (type) {
523 	case PPE_PKT_TYPE_IPV6_ROUTE_5T:
524 	case PPE_PKT_TYPE_IPV6_6RD:
525 		hwe->ipv6.src_port = be16_to_cpu(data->src_port);
526 		hwe->ipv6.dest_port = be16_to_cpu(data->dst_port);
527 		fallthrough;
528 	case PPE_PKT_TYPE_IPV6_ROUTE_3T:
529 		src = hwe->ipv6.src_ip;
530 		dest = hwe->ipv6.dest_ip;
531 		break;
532 	default:
533 		WARN_ON_ONCE(1);
534 		return -EINVAL;
535 	}
536 
537 	ipv6_addr_be32_to_cpu(src, data->v6.src_addr.s6_addr32);
538 	ipv6_addr_be32_to_cpu(dest, data->v6.dst_addr.s6_addr32);
539 
540 	return 0;
541 }
542 
airoha_ppe_foe_get_entry_hash(struct airoha_ppe * ppe,struct airoha_foe_entry * hwe)543 static u32 airoha_ppe_foe_get_entry_hash(struct airoha_ppe *ppe,
544 					 struct airoha_foe_entry *hwe)
545 {
546 	int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1);
547 	u32 ppe_hash_mask = airoha_ppe_get_total_num_entries(ppe) - 1;
548 	u32 hash, hv1, hv2, hv3;
549 
550 	switch (type) {
551 	case PPE_PKT_TYPE_IPV4_ROUTE:
552 	case PPE_PKT_TYPE_IPV4_HNAPT:
553 		hv1 = hwe->ipv4.orig_tuple.ports;
554 		hv2 = hwe->ipv4.orig_tuple.dest_ip;
555 		hv3 = hwe->ipv4.orig_tuple.src_ip;
556 		break;
557 	case PPE_PKT_TYPE_IPV6_ROUTE_3T:
558 	case PPE_PKT_TYPE_IPV6_ROUTE_5T:
559 		hv1 = hwe->ipv6.src_ip[3] ^ hwe->ipv6.dest_ip[3];
560 		hv1 ^= hwe->ipv6.ports;
561 
562 		hv2 = hwe->ipv6.src_ip[2] ^ hwe->ipv6.dest_ip[2];
563 		hv2 ^= hwe->ipv6.dest_ip[0];
564 
565 		hv3 = hwe->ipv6.src_ip[1] ^ hwe->ipv6.dest_ip[1];
566 		hv3 ^= hwe->ipv6.src_ip[0];
567 		break;
568 	case PPE_PKT_TYPE_BRIDGE: {
569 		struct airoha_foe_mac_info *l2 = &hwe->bridge.l2;
570 
571 		hv1 = l2->common.src_mac_hi & 0xffff;
572 		hv1 = hv1 << 16 | l2->src_mac_lo;
573 
574 		hv2 = l2->common.dest_mac_lo;
575 		hv2 = hv2 << 16;
576 		hv2 = hv2 | ((l2->common.src_mac_hi & 0xffff0000) >> 16);
577 
578 		hv3 = l2->common.dest_mac_hi;
579 		break;
580 	}
581 	case PPE_PKT_TYPE_IPV4_DSLITE:
582 	case PPE_PKT_TYPE_IPV6_6RD:
583 	default:
584 		WARN_ON_ONCE(1);
585 		return ppe_hash_mask;
586 	}
587 
588 	hash = (hv1 & hv2) | ((~hv1) & hv3);
589 	hash = (hash >> 24) | ((hash & 0xffffff) << 8);
590 	hash ^= hv1 ^ hv2 ^ hv3;
591 	hash ^= hash >> 16;
592 	hash &= ppe_hash_mask;
593 
594 	return hash;
595 }
596 
airoha_ppe_foe_get_flow_stats_index(struct airoha_ppe * ppe,u32 hash,u32 * index)597 static int airoha_ppe_foe_get_flow_stats_index(struct airoha_ppe *ppe,
598 					       u32 hash, u32 *index)
599 {
600 	int ppe_num_stats_entries;
601 
602 	ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
603 	if (ppe_num_stats_entries < 0)
604 		return ppe_num_stats_entries;
605 
606 	*index = hash >= ppe_num_stats_entries ? hash - PPE_STATS_NUM_ENTRIES
607 					       : hash;
608 
609 	return 0;
610 }
611 
airoha_ppe_foe_flow_stat_entry_reset(struct airoha_ppe * ppe,struct airoha_npu * npu,int index)612 static void airoha_ppe_foe_flow_stat_entry_reset(struct airoha_ppe *ppe,
613 						 struct airoha_npu *npu,
614 						 int index)
615 {
616 	memset_io(&npu->stats[index], 0, sizeof(*npu->stats));
617 	memset(&ppe->foe_stats[index], 0, sizeof(*ppe->foe_stats));
618 }
619 
airoha_ppe_foe_flow_stats_reset(struct airoha_ppe * ppe,struct airoha_npu * npu)620 static void airoha_ppe_foe_flow_stats_reset(struct airoha_ppe *ppe,
621 					    struct airoha_npu *npu)
622 {
623 	int i, ppe_num_stats_entries;
624 
625 	ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
626 	if (ppe_num_stats_entries < 0)
627 		return;
628 
629 	for (i = 0; i < ppe_num_stats_entries; i++)
630 		airoha_ppe_foe_flow_stat_entry_reset(ppe, npu, i);
631 }
632 
airoha_ppe_foe_flow_stats_update(struct airoha_ppe * ppe,struct airoha_npu * npu,struct airoha_foe_entry * hwe,u32 hash)633 static void airoha_ppe_foe_flow_stats_update(struct airoha_ppe *ppe,
634 					     struct airoha_npu *npu,
635 					     struct airoha_foe_entry *hwe,
636 					     u32 hash)
637 {
638 	int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1);
639 	u32 index, pse_port, val, *data, *ib2, *meter;
640 	int ppe_num_stats_entries;
641 	u8 nbq;
642 
643 	ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
644 	if (ppe_num_stats_entries < 0)
645 		return;
646 
647 	if (airoha_ppe_foe_get_flow_stats_index(ppe, hash, &index))
648 		return;
649 
650 	if (index >= ppe_num_stats_entries)
651 		return;
652 
653 	if (type == PPE_PKT_TYPE_BRIDGE) {
654 		data = &hwe->bridge.data;
655 		ib2 = &hwe->bridge.ib2;
656 		meter = &hwe->bridge.l2.meter;
657 	} else if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) {
658 		data = &hwe->ipv6.data;
659 		ib2 = &hwe->ipv6.ib2;
660 		meter = &hwe->ipv6.meter;
661 	} else {
662 		data = &hwe->ipv4.data;
663 		ib2 = &hwe->ipv4.ib2;
664 		meter = &hwe->ipv4.l2.meter;
665 	}
666 
667 	pse_port = FIELD_GET(AIROHA_FOE_IB2_PSE_PORT, *ib2);
668 	if (pse_port == FE_PSE_PORT_CDM4)
669 		return;
670 
671 	airoha_ppe_foe_flow_stat_entry_reset(ppe, npu, index);
672 
673 	val = FIELD_GET(AIROHA_FOE_CHANNEL | AIROHA_FOE_QID, *data);
674 	*data = (*data & ~AIROHA_FOE_ACTDP) |
675 		FIELD_PREP(AIROHA_FOE_ACTDP, val);
676 
677 	val = *ib2 & (AIROHA_FOE_IB2_NBQ | AIROHA_FOE_IB2_PSE_PORT |
678 		      AIROHA_FOE_IB2_PSE_QOS | AIROHA_FOE_IB2_FAST_PATH);
679 	*meter |= FIELD_PREP(AIROHA_FOE_TUNNEL_MTU, val);
680 
681 	nbq = pse_port == 1 ? 6 : 5;
682 	*ib2 &= ~(AIROHA_FOE_IB2_NBQ | AIROHA_FOE_IB2_PSE_PORT |
683 		  AIROHA_FOE_IB2_PSE_QOS);
684 	*ib2 |= FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT, 6) |
685 		FIELD_PREP(AIROHA_FOE_IB2_NBQ, nbq);
686 }
687 
688 static struct airoha_foe_entry *
airoha_ppe_foe_get_entry_locked(struct airoha_ppe * ppe,u32 hash)689 airoha_ppe_foe_get_entry_locked(struct airoha_ppe *ppe, u32 hash)
690 {
691 	u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe);
692 
693 	lockdep_assert_held(&ppe_lock);
694 
695 	if (hash < sram_num_entries) {
696 		u32 *hwe = ppe->foe + hash * sizeof(struct airoha_foe_entry);
697 		bool ppe2 = hash >= PPE_SRAM_NUM_ENTRIES;
698 		struct airoha_eth *eth = ppe->eth;
699 		u32 val;
700 		int i;
701 
702 		airoha_fe_wr(ppe->eth, REG_PPE_RAM_CTRL(ppe2),
703 			     FIELD_PREP(PPE_SRAM_CTRL_ENTRY_MASK, hash) |
704 			     PPE_SRAM_CTRL_REQ_MASK);
705 		if (read_poll_timeout_atomic(airoha_fe_rr, val,
706 					     val & PPE_SRAM_CTRL_ACK_MASK,
707 					     10, 100, false, eth,
708 					     REG_PPE_RAM_CTRL(ppe2)))
709 			return NULL;
710 
711 		for (i = 0; i < sizeof(struct airoha_foe_entry) / sizeof(*hwe);
712 		     i++)
713 			hwe[i] = airoha_fe_rr(eth,
714 					      REG_PPE_RAM_ENTRY(ppe2, i));
715 	}
716 
717 	return ppe->foe + hash * sizeof(struct airoha_foe_entry);
718 }
719 
airoha_ppe_foe_get_entry(struct airoha_ppe * ppe,u32 hash)720 struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe,
721 						  u32 hash)
722 {
723 	struct airoha_foe_entry *hwe;
724 
725 	spin_lock_bh(&ppe_lock);
726 	hwe = airoha_ppe_foe_get_entry_locked(ppe, hash);
727 	spin_unlock_bh(&ppe_lock);
728 
729 	return hwe;
730 }
731 
airoha_ppe_foe_compare_entry(struct airoha_flow_table_entry * e,struct airoha_foe_entry * hwe)732 static bool airoha_ppe_foe_compare_entry(struct airoha_flow_table_entry *e,
733 					 struct airoha_foe_entry *hwe)
734 {
735 	int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, e->data.ib1);
736 	int len;
737 
738 	if ((hwe->ib1 ^ e->data.ib1) & AIROHA_FOE_IB1_BIND_UDP)
739 		return false;
740 
741 	if (type > PPE_PKT_TYPE_IPV4_DSLITE)
742 		len = offsetof(struct airoha_foe_entry, ipv6.data);
743 	else
744 		len = offsetof(struct airoha_foe_entry, ipv4.ib2);
745 
746 	return !memcmp(&e->data.d, &hwe->d, len - sizeof(hwe->ib1));
747 }
748 
airoha_ppe_foe_commit_sram_entry(struct airoha_ppe * ppe,u32 hash)749 static int airoha_ppe_foe_commit_sram_entry(struct airoha_ppe *ppe, u32 hash)
750 {
751 	struct airoha_foe_entry *hwe = ppe->foe + hash * sizeof(*hwe);
752 	bool ppe2 = hash >= PPE_SRAM_NUM_ENTRIES;
753 	u32 *ptr = (u32 *)hwe, val;
754 	int i;
755 
756 	for (i = 0; i < sizeof(*hwe) / sizeof(*ptr); i++)
757 		airoha_fe_wr(ppe->eth, REG_PPE_RAM_ENTRY(ppe2, i), ptr[i]);
758 
759 	wmb();
760 	airoha_fe_wr(ppe->eth, REG_PPE_RAM_CTRL(ppe2),
761 		     FIELD_PREP(PPE_SRAM_CTRL_ENTRY_MASK, hash) |
762 		     PPE_SRAM_CTRL_WR_MASK | PPE_SRAM_CTRL_REQ_MASK);
763 
764 	return read_poll_timeout_atomic(airoha_fe_rr, val,
765 					val & PPE_SRAM_CTRL_ACK_MASK,
766 					10, 100, false, ppe->eth,
767 					REG_PPE_RAM_CTRL(ppe2));
768 }
769 
airoha_ppe_foe_commit_entry(struct airoha_ppe * ppe,struct airoha_foe_entry * e,u32 hash,bool rx_wlan)770 static int airoha_ppe_foe_commit_entry(struct airoha_ppe *ppe,
771 				       struct airoha_foe_entry *e,
772 				       u32 hash, bool rx_wlan)
773 {
774 	u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe);
775 	struct airoha_foe_entry *hwe = ppe->foe + hash * sizeof(*hwe);
776 	u32 ts = airoha_ppe_get_timestamp(ppe);
777 	struct airoha_eth *eth = ppe->eth;
778 	struct airoha_npu *npu;
779 	int err = 0;
780 
781 	memcpy(&hwe->d, &e->d, sizeof(*hwe) - sizeof(hwe->ib1));
782 	wmb();
783 
784 	e->ib1 &= ~AIROHA_FOE_IB1_BIND_TIMESTAMP;
785 	e->ib1 |= FIELD_PREP(AIROHA_FOE_IB1_BIND_TIMESTAMP, ts);
786 	hwe->ib1 = e->ib1;
787 
788 	rcu_read_lock();
789 
790 	npu = rcu_dereference(eth->npu);
791 	if (!npu) {
792 		err = -ENODEV;
793 		goto unlock;
794 	}
795 
796 	if (!rx_wlan)
797 		airoha_ppe_foe_flow_stats_update(ppe, npu, hwe, hash);
798 
799 	if (hash < sram_num_entries)
800 		err = airoha_ppe_foe_commit_sram_entry(ppe, hash);
801 unlock:
802 	rcu_read_unlock();
803 
804 	return err;
805 }
806 
airoha_ppe_foe_remove_flow(struct airoha_ppe * ppe,struct airoha_flow_table_entry * e)807 static void airoha_ppe_foe_remove_flow(struct airoha_ppe *ppe,
808 				       struct airoha_flow_table_entry *e)
809 {
810 	lockdep_assert_held(&ppe_lock);
811 
812 	hlist_del_init(&e->list);
813 	if (e->hash != 0xffff) {
814 		e->data.ib1 &= ~AIROHA_FOE_IB1_BIND_STATE;
815 		e->data.ib1 |= FIELD_PREP(AIROHA_FOE_IB1_BIND_STATE,
816 					  AIROHA_FOE_STATE_INVALID);
817 		airoha_ppe_foe_commit_entry(ppe, &e->data, e->hash, false);
818 		e->hash = 0xffff;
819 	}
820 	if (e->type == FLOW_TYPE_L2_SUBFLOW) {
821 		hlist_del_init(&e->l2_subflow_node);
822 		kfree(e);
823 	}
824 }
825 
airoha_ppe_foe_remove_l2_flow(struct airoha_ppe * ppe,struct airoha_flow_table_entry * e)826 static void airoha_ppe_foe_remove_l2_flow(struct airoha_ppe *ppe,
827 					  struct airoha_flow_table_entry *e)
828 {
829 	struct hlist_head *head = &e->l2_flows;
830 	struct hlist_node *n;
831 
832 	lockdep_assert_held(&ppe_lock);
833 
834 	rhashtable_remove_fast(&ppe->l2_flows, &e->l2_node,
835 			       airoha_l2_flow_table_params);
836 	hlist_for_each_entry_safe(e, n, head, l2_subflow_node)
837 		airoha_ppe_foe_remove_flow(ppe, e);
838 }
839 
airoha_ppe_foe_flow_remove_entry(struct airoha_ppe * ppe,struct airoha_flow_table_entry * e)840 static void airoha_ppe_foe_flow_remove_entry(struct airoha_ppe *ppe,
841 					     struct airoha_flow_table_entry *e)
842 {
843 	spin_lock_bh(&ppe_lock);
844 
845 	if (e->type == FLOW_TYPE_L2)
846 		airoha_ppe_foe_remove_l2_flow(ppe, e);
847 	else
848 		airoha_ppe_foe_remove_flow(ppe, e);
849 
850 	spin_unlock_bh(&ppe_lock);
851 }
852 
853 static int
airoha_ppe_foe_commit_subflow_entry(struct airoha_ppe * ppe,struct airoha_flow_table_entry * e,u32 hash,bool rx_wlan)854 airoha_ppe_foe_commit_subflow_entry(struct airoha_ppe *ppe,
855 				    struct airoha_flow_table_entry *e,
856 				    u32 hash, bool rx_wlan)
857 {
858 	u32 mask = AIROHA_FOE_IB1_BIND_PACKET_TYPE | AIROHA_FOE_IB1_BIND_UDP;
859 	struct airoha_foe_entry *hwe_p, hwe;
860 	struct airoha_flow_table_entry *f;
861 	int type;
862 
863 	hwe_p = airoha_ppe_foe_get_entry_locked(ppe, hash);
864 	if (!hwe_p)
865 		return -EINVAL;
866 
867 	f = kzalloc_obj(*f, GFP_ATOMIC);
868 	if (!f)
869 		return -ENOMEM;
870 
871 	hlist_add_head(&f->l2_subflow_node, &e->l2_flows);
872 	f->type = FLOW_TYPE_L2_SUBFLOW;
873 	f->hash = hash;
874 
875 	memcpy(&hwe, hwe_p, sizeof(*hwe_p));
876 	hwe.ib1 = (hwe.ib1 & mask) | (e->data.ib1 & ~mask);
877 
878 	type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe.ib1);
879 	if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) {
880 		memcpy(&hwe.ipv6.l2, &e->data.bridge.l2, sizeof(hwe.ipv6.l2));
881 		hwe.ipv6.ib2 = e->data.bridge.ib2;
882 		/* setting smac_id to 0xf instruct the hw to keep original
883 		 * source mac address
884 		 */
885 		hwe.ipv6.l2.src_mac_hi = FIELD_PREP(AIROHA_FOE_MAC_SMAC_ID,
886 						    0xf);
887 	} else {
888 		memcpy(&hwe.bridge.l2, &e->data.bridge.l2,
889 		       sizeof(hwe.bridge.l2));
890 		hwe.bridge.ib2 = e->data.bridge.ib2;
891 		if (type == PPE_PKT_TYPE_IPV4_HNAPT)
892 			memcpy(&hwe.ipv4.new_tuple, &hwe.ipv4.orig_tuple,
893 			       sizeof(hwe.ipv4.new_tuple));
894 	}
895 
896 	hwe.bridge.data = e->data.bridge.data;
897 	airoha_ppe_foe_commit_entry(ppe, &hwe, hash, rx_wlan);
898 
899 	return 0;
900 }
901 
airoha_ppe_foe_insert_entry(struct airoha_ppe * ppe,struct sk_buff * skb,u32 hash,bool rx_wlan)902 static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe,
903 					struct sk_buff *skb,
904 					u32 hash, bool rx_wlan)
905 {
906 	struct airoha_flow_table_entry *e;
907 	struct airoha_foe_bridge br = {};
908 	struct airoha_foe_entry *hwe;
909 	bool commit_done = false;
910 	struct hlist_node *n;
911 	u32 index, state;
912 
913 	spin_lock_bh(&ppe_lock);
914 
915 	hwe = airoha_ppe_foe_get_entry_locked(ppe, hash);
916 	if (!hwe)
917 		goto unlock;
918 
919 	state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, hwe->ib1);
920 	if (state == AIROHA_FOE_STATE_BIND)
921 		goto unlock;
922 
923 	index = airoha_ppe_foe_get_entry_hash(ppe, hwe);
924 	hlist_for_each_entry_safe(e, n, &ppe->foe_flow[index], list) {
925 		if (e->type == FLOW_TYPE_L2_SUBFLOW) {
926 			state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, hwe->ib1);
927 			if (state != AIROHA_FOE_STATE_BIND) {
928 				e->hash = 0xffff;
929 				airoha_ppe_foe_remove_flow(ppe, e);
930 			}
931 			continue;
932 		}
933 
934 		if (!airoha_ppe_foe_compare_entry(e, hwe))
935 			continue;
936 
937 		airoha_ppe_foe_commit_entry(ppe, &e->data, hash, rx_wlan);
938 		commit_done = true;
939 		e->hash = hash;
940 	}
941 
942 	if (commit_done)
943 		goto unlock;
944 
945 	airoha_ppe_foe_set_bridge_addrs(&br, eth_hdr(skb));
946 	e = rhashtable_lookup_fast(&ppe->l2_flows, &br,
947 				   airoha_l2_flow_table_params);
948 	if (e)
949 		airoha_ppe_foe_commit_subflow_entry(ppe, e, hash, rx_wlan);
950 unlock:
951 	spin_unlock_bh(&ppe_lock);
952 }
953 
954 static int
airoha_ppe_foe_l2_flow_commit_entry(struct airoha_ppe * ppe,struct airoha_flow_table_entry * e)955 airoha_ppe_foe_l2_flow_commit_entry(struct airoha_ppe *ppe,
956 				    struct airoha_flow_table_entry *e)
957 {
958 	struct airoha_flow_table_entry *prev;
959 
960 	e->type = FLOW_TYPE_L2;
961 	prev = rhashtable_lookup_get_insert_fast(&ppe->l2_flows, &e->l2_node,
962 						 airoha_l2_flow_table_params);
963 	if (!prev)
964 		return 0;
965 
966 	if (IS_ERR(prev))
967 		return PTR_ERR(prev);
968 
969 	return rhashtable_replace_fast(&ppe->l2_flows, &prev->l2_node,
970 				       &e->l2_node,
971 				       airoha_l2_flow_table_params);
972 }
973 
airoha_ppe_foe_flow_commit_entry(struct airoha_ppe * ppe,struct airoha_flow_table_entry * e)974 static int airoha_ppe_foe_flow_commit_entry(struct airoha_ppe *ppe,
975 					    struct airoha_flow_table_entry *e)
976 {
977 	int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, e->data.ib1);
978 	u32 hash;
979 
980 	if (type == PPE_PKT_TYPE_BRIDGE)
981 		return airoha_ppe_foe_l2_flow_commit_entry(ppe, e);
982 
983 	hash = airoha_ppe_foe_get_entry_hash(ppe, &e->data);
984 	e->type = FLOW_TYPE_L4;
985 	e->hash = 0xffff;
986 
987 	spin_lock_bh(&ppe_lock);
988 	hlist_add_head(&e->list, &ppe->foe_flow[hash]);
989 	spin_unlock_bh(&ppe_lock);
990 
991 	return 0;
992 }
993 
airoha_ppe_get_entry_idle_time(struct airoha_ppe * ppe,u32 ib1)994 static int airoha_ppe_get_entry_idle_time(struct airoha_ppe *ppe, u32 ib1)
995 {
996 	u32 state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, ib1);
997 	u32 ts, ts_mask, now = airoha_ppe_get_timestamp(ppe);
998 	int idle;
999 
1000 	if (state == AIROHA_FOE_STATE_BIND) {
1001 		ts = FIELD_GET(AIROHA_FOE_IB1_BIND_TIMESTAMP, ib1);
1002 		ts_mask = AIROHA_FOE_IB1_BIND_TIMESTAMP;
1003 	} else {
1004 		ts = FIELD_GET(AIROHA_FOE_IB1_UNBIND_TIMESTAMP, ib1);
1005 		now = FIELD_GET(AIROHA_FOE_IB1_UNBIND_TIMESTAMP, now);
1006 		ts_mask = AIROHA_FOE_IB1_UNBIND_TIMESTAMP;
1007 	}
1008 	idle = now - ts;
1009 
1010 	return idle < 0 ? idle + ts_mask + 1 : idle;
1011 }
1012 
1013 static void
airoha_ppe_foe_flow_l2_entry_update(struct airoha_ppe * ppe,struct airoha_flow_table_entry * e)1014 airoha_ppe_foe_flow_l2_entry_update(struct airoha_ppe *ppe,
1015 				    struct airoha_flow_table_entry *e)
1016 {
1017 	int min_idle = airoha_ppe_get_entry_idle_time(ppe, e->data.ib1);
1018 	struct airoha_flow_table_entry *iter;
1019 	struct hlist_node *n;
1020 
1021 	lockdep_assert_held(&ppe_lock);
1022 
1023 	hlist_for_each_entry_safe(iter, n, &e->l2_flows, l2_subflow_node) {
1024 		struct airoha_foe_entry *hwe;
1025 		u32 ib1, state;
1026 		int idle;
1027 
1028 		hwe = airoha_ppe_foe_get_entry_locked(ppe, iter->hash);
1029 		if (!hwe)
1030 			continue;
1031 
1032 		ib1 = READ_ONCE(hwe->ib1);
1033 		state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, ib1);
1034 		if (state != AIROHA_FOE_STATE_BIND) {
1035 			iter->hash = 0xffff;
1036 			airoha_ppe_foe_remove_flow(ppe, iter);
1037 			continue;
1038 		}
1039 
1040 		idle = airoha_ppe_get_entry_idle_time(ppe, ib1);
1041 		if (idle >= min_idle)
1042 			continue;
1043 
1044 		min_idle = idle;
1045 		e->data.ib1 &= ~AIROHA_FOE_IB1_BIND_TIMESTAMP;
1046 		e->data.ib1 |= ib1 & AIROHA_FOE_IB1_BIND_TIMESTAMP;
1047 	}
1048 }
1049 
airoha_ppe_foe_flow_entry_update(struct airoha_ppe * ppe,struct airoha_flow_table_entry * e)1050 static void airoha_ppe_foe_flow_entry_update(struct airoha_ppe *ppe,
1051 					     struct airoha_flow_table_entry *e)
1052 {
1053 	struct airoha_foe_entry *hwe_p, hwe = {};
1054 
1055 	spin_lock_bh(&ppe_lock);
1056 
1057 	if (e->type == FLOW_TYPE_L2) {
1058 		airoha_ppe_foe_flow_l2_entry_update(ppe, e);
1059 		goto unlock;
1060 	}
1061 
1062 	if (e->hash == 0xffff)
1063 		goto unlock;
1064 
1065 	hwe_p = airoha_ppe_foe_get_entry_locked(ppe, e->hash);
1066 	if (!hwe_p)
1067 		goto unlock;
1068 
1069 	memcpy(&hwe, hwe_p, sizeof(*hwe_p));
1070 	if (!airoha_ppe_foe_compare_entry(e, &hwe)) {
1071 		e->hash = 0xffff;
1072 		goto unlock;
1073 	}
1074 
1075 	e->data.ib1 = hwe.ib1;
1076 unlock:
1077 	spin_unlock_bh(&ppe_lock);
1078 }
1079 
airoha_ppe_entry_idle_time(struct airoha_ppe * ppe,struct airoha_flow_table_entry * e)1080 static int airoha_ppe_entry_idle_time(struct airoha_ppe *ppe,
1081 				      struct airoha_flow_table_entry *e)
1082 {
1083 	airoha_ppe_foe_flow_entry_update(ppe, e);
1084 
1085 	return airoha_ppe_get_entry_idle_time(ppe, e->data.ib1);
1086 }
1087 
airoha_ppe_flow_offload_replace(struct airoha_eth * eth,struct flow_cls_offload * f)1088 static int airoha_ppe_flow_offload_replace(struct airoha_eth *eth,
1089 					   struct flow_cls_offload *f)
1090 {
1091 	struct flow_rule *rule = flow_cls_offload_flow_rule(f);
1092 	struct airoha_flow_table_entry *e;
1093 	struct airoha_flow_data data = {};
1094 	struct net_device *odev = NULL;
1095 	struct flow_action_entry *act;
1096 	u8 l4proto = 0, priority = 0;
1097 	struct airoha_foe_entry hwe;
1098 	int err, i, offload_type;
1099 	u16 addr_type = 0;
1100 
1101 	if (rhashtable_lookup(&eth->flow_table, &f->cookie,
1102 			      airoha_flow_table_params))
1103 		return -EEXIST;
1104 
1105 	if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META))
1106 		return -EOPNOTSUPP;
1107 
1108 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
1109 		struct flow_match_control match;
1110 
1111 		flow_rule_match_control(rule, &match);
1112 		addr_type = match.key->addr_type;
1113 		if (flow_rule_has_control_flags(match.mask->flags,
1114 						f->common.extack))
1115 			return -EOPNOTSUPP;
1116 	} else {
1117 		return -EOPNOTSUPP;
1118 	}
1119 
1120 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
1121 		struct flow_match_basic match;
1122 
1123 		flow_rule_match_basic(rule, &match);
1124 		l4proto = match.key->ip_proto;
1125 	} else {
1126 		return -EOPNOTSUPP;
1127 	}
1128 
1129 	switch (addr_type) {
1130 	case 0:
1131 		offload_type = PPE_PKT_TYPE_BRIDGE;
1132 		if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
1133 			struct flow_match_eth_addrs match;
1134 
1135 			flow_rule_match_eth_addrs(rule, &match);
1136 			memcpy(data.eth.h_dest, match.key->dst, ETH_ALEN);
1137 			memcpy(data.eth.h_source, match.key->src, ETH_ALEN);
1138 		} else {
1139 			return -EOPNOTSUPP;
1140 		}
1141 		break;
1142 	case FLOW_DISSECTOR_KEY_IPV4_ADDRS:
1143 		offload_type = PPE_PKT_TYPE_IPV4_HNAPT;
1144 		break;
1145 	case FLOW_DISSECTOR_KEY_IPV6_ADDRS:
1146 		offload_type = PPE_PKT_TYPE_IPV6_ROUTE_5T;
1147 		break;
1148 	default:
1149 		return -EOPNOTSUPP;
1150 	}
1151 
1152 	flow_action_for_each(i, act, &rule->action) {
1153 		switch (act->id) {
1154 		case FLOW_ACTION_MANGLE:
1155 			if (offload_type == PPE_PKT_TYPE_BRIDGE)
1156 				return -EOPNOTSUPP;
1157 
1158 			if (act->mangle.htype == FLOW_ACT_MANGLE_HDR_TYPE_ETH)
1159 				airoha_ppe_flow_mangle_eth(act, &data.eth);
1160 			break;
1161 		case FLOW_ACTION_REDIRECT:
1162 			odev = act->dev;
1163 			break;
1164 		case FLOW_ACTION_CSUM:
1165 			break;
1166 		case FLOW_ACTION_VLAN_PUSH:
1167 			if (data.vlan.num == 2 ||
1168 			    act->vlan.proto != htons(ETH_P_8021Q))
1169 				return -EOPNOTSUPP;
1170 
1171 			data.vlan.hdr[data.vlan.num].id = act->vlan.vid;
1172 			data.vlan.hdr[data.vlan.num].proto = act->vlan.proto;
1173 			data.vlan.num++;
1174 			break;
1175 		case FLOW_ACTION_VLAN_POP:
1176 			break;
1177 		case FLOW_ACTION_PPPOE_PUSH:
1178 			if (data.pppoe.num == 1 || data.vlan.num == 2)
1179 				return -EOPNOTSUPP;
1180 
1181 			data.pppoe.sid = act->pppoe.sid;
1182 			data.pppoe.num++;
1183 			break;
1184 		default:
1185 			return -EOPNOTSUPP;
1186 		}
1187 	}
1188 
1189 	if (!is_valid_ether_addr(data.eth.h_source) ||
1190 	    !is_valid_ether_addr(data.eth.h_dest))
1191 		return -EINVAL;
1192 
1193 	err = airoha_ppe_foe_entry_prepare(eth, &hwe, odev, offload_type,
1194 					   &data, l4proto, priority);
1195 	if (err)
1196 		return err;
1197 
1198 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
1199 		struct flow_match_ports ports;
1200 
1201 		if (offload_type == PPE_PKT_TYPE_BRIDGE)
1202 			return -EOPNOTSUPP;
1203 
1204 		flow_rule_match_ports(rule, &ports);
1205 		data.src_port = ports.key->src;
1206 		data.dst_port = ports.key->dst;
1207 	} else if (offload_type != PPE_PKT_TYPE_BRIDGE) {
1208 		return -EOPNOTSUPP;
1209 	}
1210 
1211 	if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
1212 		struct flow_match_ipv4_addrs addrs;
1213 
1214 		flow_rule_match_ipv4_addrs(rule, &addrs);
1215 		data.v4.src_addr = addrs.key->src;
1216 		data.v4.dst_addr = addrs.key->dst;
1217 		airoha_ppe_foe_entry_set_ipv4_tuple(&hwe, &data, false);
1218 	}
1219 
1220 	if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
1221 		struct flow_match_ipv6_addrs addrs;
1222 
1223 		flow_rule_match_ipv6_addrs(rule, &addrs);
1224 
1225 		data.v6.src_addr = addrs.key->src;
1226 		data.v6.dst_addr = addrs.key->dst;
1227 		airoha_ppe_foe_entry_set_ipv6_tuple(&hwe, &data);
1228 	}
1229 
1230 	flow_action_for_each(i, act, &rule->action) {
1231 		if (act->id != FLOW_ACTION_MANGLE)
1232 			continue;
1233 
1234 		if (offload_type == PPE_PKT_TYPE_BRIDGE)
1235 			return -EOPNOTSUPP;
1236 
1237 		switch (act->mangle.htype) {
1238 		case FLOW_ACT_MANGLE_HDR_TYPE_TCP:
1239 		case FLOW_ACT_MANGLE_HDR_TYPE_UDP:
1240 			err = airoha_ppe_flow_mangle_ports(act, &data);
1241 			break;
1242 		case FLOW_ACT_MANGLE_HDR_TYPE_IP4:
1243 			err = airoha_ppe_flow_mangle_ipv4(act, &data);
1244 			break;
1245 		case FLOW_ACT_MANGLE_HDR_TYPE_ETH:
1246 			/* handled earlier */
1247 			break;
1248 		default:
1249 			return -EOPNOTSUPP;
1250 		}
1251 
1252 		if (err)
1253 			return err;
1254 	}
1255 
1256 	if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
1257 		err = airoha_ppe_foe_entry_set_ipv4_tuple(&hwe, &data, true);
1258 		if (err)
1259 			return err;
1260 	}
1261 
1262 	e = kzalloc_obj(*e);
1263 	if (!e)
1264 		return -ENOMEM;
1265 
1266 	e->cookie = f->cookie;
1267 	memcpy(&e->data, &hwe, sizeof(e->data));
1268 
1269 	err = airoha_ppe_foe_flow_commit_entry(eth->ppe, e);
1270 	if (err)
1271 		goto free_entry;
1272 
1273 	err = rhashtable_insert_fast(&eth->flow_table, &e->node,
1274 				     airoha_flow_table_params);
1275 	if (err < 0)
1276 		goto remove_foe_entry;
1277 
1278 	return 0;
1279 
1280 remove_foe_entry:
1281 	airoha_ppe_foe_flow_remove_entry(eth->ppe, e);
1282 free_entry:
1283 	kfree(e);
1284 
1285 	return err;
1286 }
1287 
airoha_ppe_flow_offload_destroy(struct airoha_eth * eth,struct flow_cls_offload * f)1288 static int airoha_ppe_flow_offload_destroy(struct airoha_eth *eth,
1289 					   struct flow_cls_offload *f)
1290 {
1291 	struct airoha_flow_table_entry *e;
1292 
1293 	e = rhashtable_lookup(&eth->flow_table, &f->cookie,
1294 			      airoha_flow_table_params);
1295 	if (!e)
1296 		return -ENOENT;
1297 
1298 	airoha_ppe_foe_flow_remove_entry(eth->ppe, e);
1299 	rhashtable_remove_fast(&eth->flow_table, &e->node,
1300 			       airoha_flow_table_params);
1301 	kfree(e);
1302 
1303 	return 0;
1304 }
1305 
airoha_ppe_foe_entry_get_stats(struct airoha_ppe * ppe,u32 hash,struct airoha_foe_stats64 * stats)1306 void airoha_ppe_foe_entry_get_stats(struct airoha_ppe *ppe, u32 hash,
1307 				    struct airoha_foe_stats64 *stats)
1308 {
1309 	struct airoha_eth *eth = ppe->eth;
1310 	int ppe_num_stats_entries;
1311 	struct airoha_npu *npu;
1312 	u32 index;
1313 
1314 	ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
1315 	if (ppe_num_stats_entries < 0)
1316 		return;
1317 
1318 	if (airoha_ppe_foe_get_flow_stats_index(ppe, hash, &index))
1319 		return;
1320 
1321 	if (index >= ppe_num_stats_entries)
1322 		return;
1323 
1324 	rcu_read_lock();
1325 
1326 	npu = rcu_dereference(eth->npu);
1327 	if (npu) {
1328 		u64 packets = ppe->foe_stats[index].packets;
1329 		u64 bytes = ppe->foe_stats[index].bytes;
1330 		struct airoha_foe_stats npu_stats;
1331 
1332 		memcpy_fromio(&npu_stats, &npu->stats[index],
1333 			      sizeof(*npu->stats));
1334 		stats->packets = packets << 32 | npu_stats.packets;
1335 		stats->bytes = bytes << 32 | npu_stats.bytes;
1336 	}
1337 
1338 	rcu_read_unlock();
1339 }
1340 
airoha_ppe_flow_offload_stats(struct airoha_eth * eth,struct flow_cls_offload * f)1341 static int airoha_ppe_flow_offload_stats(struct airoha_eth *eth,
1342 					 struct flow_cls_offload *f)
1343 {
1344 	struct airoha_flow_table_entry *e;
1345 	u32 idle;
1346 
1347 	e = rhashtable_lookup(&eth->flow_table, &f->cookie,
1348 			      airoha_flow_table_params);
1349 	if (!e)
1350 		return -ENOENT;
1351 
1352 	idle = airoha_ppe_entry_idle_time(eth->ppe, e);
1353 	f->stats.lastused = jiffies - idle * HZ;
1354 
1355 	if (e->hash != 0xffff) {
1356 		struct airoha_foe_stats64 stats = {};
1357 
1358 		airoha_ppe_foe_entry_get_stats(eth->ppe, e->hash, &stats);
1359 		f->stats.pkts += (stats.packets - e->stats.packets);
1360 		f->stats.bytes += (stats.bytes - e->stats.bytes);
1361 		e->stats = stats;
1362 	}
1363 
1364 	return 0;
1365 }
1366 
airoha_ppe_flow_offload_cmd(struct airoha_eth * eth,struct flow_cls_offload * f)1367 static int airoha_ppe_flow_offload_cmd(struct airoha_eth *eth,
1368 				       struct flow_cls_offload *f)
1369 {
1370 	switch (f->command) {
1371 	case FLOW_CLS_REPLACE:
1372 		return airoha_ppe_flow_offload_replace(eth, f);
1373 	case FLOW_CLS_DESTROY:
1374 		return airoha_ppe_flow_offload_destroy(eth, f);
1375 	case FLOW_CLS_STATS:
1376 		return airoha_ppe_flow_offload_stats(eth, f);
1377 	default:
1378 		break;
1379 	}
1380 
1381 	return -EOPNOTSUPP;
1382 }
1383 
airoha_ppe_flush_sram_entries(struct airoha_ppe * ppe)1384 static int airoha_ppe_flush_sram_entries(struct airoha_ppe *ppe)
1385 {
1386 	u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe);
1387 	struct airoha_foe_entry *hwe = ppe->foe;
1388 	int i;
1389 
1390 	for (i = 0; i < sram_num_entries; i++) {
1391 		int err;
1392 
1393 		memset(&hwe[i], 0, sizeof(*hwe));
1394 		err = airoha_ppe_foe_commit_sram_entry(ppe, i);
1395 		if (err)
1396 			return err;
1397 	}
1398 
1399 	return 0;
1400 }
1401 
airoha_ppe_npu_get(struct airoha_eth * eth)1402 static struct airoha_npu *airoha_ppe_npu_get(struct airoha_eth *eth)
1403 {
1404 	struct airoha_npu *npu = airoha_npu_get(eth->dev);
1405 
1406 	if (IS_ERR(npu)) {
1407 		request_module("airoha-npu");
1408 		npu = airoha_npu_get(eth->dev);
1409 	}
1410 
1411 	return npu;
1412 }
1413 
airoha_ppe_wait_for_npu_init(struct airoha_eth * eth)1414 static int airoha_ppe_wait_for_npu_init(struct airoha_eth *eth)
1415 {
1416 	int err;
1417 	u32 val;
1418 
1419 	/* PPE_FLOW_CFG default register value is 0. Since we reset FE
1420 	 * during the device probe we can just check the configured value
1421 	 * is not 0 here.
1422 	 */
1423 	err = read_poll_timeout(airoha_fe_rr, val, val, USEC_PER_MSEC,
1424 				100 * USEC_PER_MSEC, false, eth,
1425 				REG_PPE_PPE_FLOW_CFG(0));
1426 	if (err)
1427 		return err;
1428 
1429 	if (airoha_ppe_is_enabled(eth, 1))
1430 		err = read_poll_timeout(airoha_fe_rr, val, val, USEC_PER_MSEC,
1431 					100 * USEC_PER_MSEC, false, eth,
1432 					REG_PPE_PPE_FLOW_CFG(1));
1433 
1434 	return err;
1435 }
1436 
airoha_ppe_offload_setup(struct airoha_eth * eth)1437 static int airoha_ppe_offload_setup(struct airoha_eth *eth)
1438 {
1439 	struct airoha_npu *npu = airoha_ppe_npu_get(eth);
1440 	struct airoha_ppe *ppe = eth->ppe;
1441 	int err, ppe_num_stats_entries;
1442 
1443 	if (IS_ERR(npu))
1444 		return PTR_ERR(npu);
1445 
1446 	err = npu->ops.ppe_init(npu);
1447 	if (err)
1448 		goto error_npu_put;
1449 
1450 	/* Wait for NPU PPE configuration to complete */
1451 	err = airoha_ppe_wait_for_npu_init(eth);
1452 	if (err)
1453 		goto error_npu_put;
1454 
1455 	ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
1456 	if (ppe_num_stats_entries > 0) {
1457 		err = npu->ops.ppe_init_stats(npu, ppe->foe_stats_dma,
1458 					      ppe_num_stats_entries);
1459 		if (err)
1460 			goto error_npu_put;
1461 	}
1462 
1463 	airoha_ppe_hw_init(ppe);
1464 	airoha_ppe_foe_flow_stats_reset(ppe, npu);
1465 
1466 	rcu_assign_pointer(eth->npu, npu);
1467 	synchronize_rcu();
1468 
1469 	return 0;
1470 
1471 error_npu_put:
1472 	airoha_npu_put(npu);
1473 
1474 	return err;
1475 }
1476 
airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev * dev,void * type_data)1477 int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, void *type_data)
1478 {
1479 	struct airoha_ppe *ppe = dev->priv;
1480 	struct airoha_eth *eth = ppe->eth;
1481 	int err = 0;
1482 
1483 	/* Netfilter flowtable can try to offload flower rules while not all
1484 	 * the net_devices are registered or initialized. Delay offloading
1485 	 * until all net_devices are registered in the system.
1486 	 */
1487 	if (!test_bit(DEV_STATE_REGISTERED, &eth->state))
1488 		return -EBUSY;
1489 
1490 	mutex_lock(&flow_offload_mutex);
1491 
1492 	if (!eth->npu)
1493 		err = airoha_ppe_offload_setup(eth);
1494 	if (!err)
1495 		err = airoha_ppe_flow_offload_cmd(eth, type_data);
1496 
1497 	mutex_unlock(&flow_offload_mutex);
1498 
1499 	return err;
1500 }
1501 
airoha_ppe_check_skb(struct airoha_ppe_dev * dev,struct sk_buff * skb,u16 hash,bool rx_wlan)1502 void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb,
1503 			  u16 hash, bool rx_wlan)
1504 {
1505 	struct airoha_ppe *ppe = dev->priv;
1506 	u32 ppe_hash_mask = airoha_ppe_get_total_num_entries(ppe) - 1;
1507 	u16 now, diff;
1508 
1509 	if (hash > ppe_hash_mask)
1510 		return;
1511 
1512 	now = (u16)jiffies;
1513 	diff = now - ppe->foe_check_time[hash];
1514 	if (diff < HZ / 10)
1515 		return;
1516 
1517 	ppe->foe_check_time[hash] = now;
1518 	airoha_ppe_foe_insert_entry(ppe, skb, hash, rx_wlan);
1519 }
1520 
airoha_ppe_init_upd_mem(struct airoha_gdm_dev * dev,const u8 * addr)1521 void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev, const u8 *addr)
1522 {
1523 	struct airoha_gdm_port *port = dev->port;
1524 	struct airoha_eth *eth = dev->eth;
1525 	u32 val;
1526 
1527 	val = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | addr[5];
1528 	airoha_fe_wr(eth, REG_UPDMEM_DATA(0), val);
1529 	airoha_fe_wr(eth, REG_UPDMEM_CTRL(0),
1530 		     FIELD_PREP(PPE_UPDMEM_ADDR_MASK, port->id) |
1531 		     PPE_UPDMEM_WR_MASK | PPE_UPDMEM_REQ_MASK);
1532 
1533 	val = (addr[0] << 8) | addr[1];
1534 	airoha_fe_wr(eth, REG_UPDMEM_DATA(0), val);
1535 	airoha_fe_wr(eth, REG_UPDMEM_CTRL(0),
1536 		     FIELD_PREP(PPE_UPDMEM_ADDR_MASK, port->id) |
1537 		     FIELD_PREP(PPE_UPDMEM_OFFSET_MASK, 1) |
1538 		     PPE_UPDMEM_WR_MASK | PPE_UPDMEM_REQ_MASK);
1539 }
1540 
airoha_ppe_get_dev(struct device * dev)1541 struct airoha_ppe_dev *airoha_ppe_get_dev(struct device *dev)
1542 {
1543 	struct platform_device *pdev;
1544 	struct device_node *np;
1545 	struct airoha_eth *eth;
1546 
1547 	np = of_parse_phandle(dev->of_node, "airoha,eth", 0);
1548 	if (!np)
1549 		return ERR_PTR(-ENODEV);
1550 
1551 	pdev = of_find_device_by_node(np);
1552 	if (!pdev) {
1553 		dev_err(dev, "cannot find device node %s\n", np->name);
1554 		of_node_put(np);
1555 		return ERR_PTR(-ENODEV);
1556 	}
1557 	of_node_put(np);
1558 
1559 	if (!try_module_get(THIS_MODULE)) {
1560 		dev_err(dev, "failed to get the device driver module\n");
1561 		goto error_pdev_put;
1562 	}
1563 
1564 	eth = platform_get_drvdata(pdev);
1565 	if (!eth)
1566 		goto error_module_put;
1567 
1568 	if (!device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER)) {
1569 		dev_err(&pdev->dev,
1570 			"failed to create device link to consumer %s\n",
1571 			dev_name(dev));
1572 		goto error_module_put;
1573 	}
1574 
1575 	return &eth->ppe->dev;
1576 
1577 error_module_put:
1578 	module_put(THIS_MODULE);
1579 error_pdev_put:
1580 	platform_device_put(pdev);
1581 
1582 	return ERR_PTR(-ENODEV);
1583 }
1584 EXPORT_SYMBOL_GPL(airoha_ppe_get_dev);
1585 
airoha_ppe_put_dev(struct airoha_ppe_dev * dev)1586 void airoha_ppe_put_dev(struct airoha_ppe_dev *dev)
1587 {
1588 	struct airoha_ppe *ppe = dev->priv;
1589 	struct airoha_eth *eth = ppe->eth;
1590 
1591 	module_put(THIS_MODULE);
1592 	put_device(eth->dev);
1593 }
1594 EXPORT_SYMBOL_GPL(airoha_ppe_put_dev);
1595 
airoha_ppe_init(struct airoha_eth * eth)1596 int airoha_ppe_init(struct airoha_eth *eth)
1597 {
1598 	int foe_size, err, ppe_num_stats_entries;
1599 	u32 ppe_num_entries;
1600 	struct airoha_ppe *ppe;
1601 
1602 	ppe = devm_kzalloc(eth->dev, sizeof(*ppe), GFP_KERNEL);
1603 	if (!ppe)
1604 		return -ENOMEM;
1605 
1606 	ppe->dev.ops.setup_tc_block_cb = airoha_ppe_setup_tc_block_cb;
1607 	ppe->dev.ops.check_skb = airoha_ppe_check_skb;
1608 	ppe->dev.priv = ppe;
1609 	ppe->eth = eth;
1610 	eth->ppe = ppe;
1611 
1612 	ppe_num_entries = airoha_ppe_get_total_num_entries(ppe);
1613 	foe_size = ppe_num_entries * sizeof(struct airoha_foe_entry);
1614 	ppe->foe = dmam_alloc_coherent(eth->dev, foe_size, &ppe->foe_dma,
1615 				       GFP_KERNEL);
1616 	if (!ppe->foe)
1617 		return -ENOMEM;
1618 
1619 	ppe->foe_flow = devm_kzalloc(eth->dev,
1620 				     ppe_num_entries * sizeof(*ppe->foe_flow),
1621 				     GFP_KERNEL);
1622 	if (!ppe->foe_flow)
1623 		return -ENOMEM;
1624 
1625 	ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
1626 	if (ppe_num_stats_entries > 0) {
1627 		foe_size = ppe_num_stats_entries * sizeof(*ppe->foe_stats);
1628 		ppe->foe_stats = dmam_alloc_coherent(eth->dev, foe_size,
1629 						     &ppe->foe_stats_dma,
1630 						     GFP_KERNEL);
1631 		if (!ppe->foe_stats)
1632 			return -ENOMEM;
1633 	}
1634 
1635 	ppe->foe_check_time = devm_kzalloc(eth->dev,
1636 					   ppe_num_entries * sizeof(*ppe->foe_check_time),
1637 					   GFP_KERNEL);
1638 	if (!ppe->foe_check_time)
1639 		return -ENOMEM;
1640 
1641 	err = airoha_ppe_flush_sram_entries(ppe);
1642 	if (err)
1643 		return err;
1644 
1645 	err = rhashtable_init(&eth->flow_table, &airoha_flow_table_params);
1646 	if (err)
1647 		return err;
1648 
1649 	err = rhashtable_init(&ppe->l2_flows, &airoha_l2_flow_table_params);
1650 	if (err)
1651 		goto error_flow_table_destroy;
1652 
1653 	err = airoha_ppe_debugfs_init(ppe);
1654 	if (err)
1655 		goto error_l2_flow_table_destroy;
1656 
1657 	return 0;
1658 
1659 error_l2_flow_table_destroy:
1660 	rhashtable_destroy(&ppe->l2_flows);
1661 error_flow_table_destroy:
1662 	rhashtable_destroy(&eth->flow_table);
1663 
1664 	return err;
1665 }
1666 
airoha_ppe_deinit(struct airoha_eth * eth)1667 void airoha_ppe_deinit(struct airoha_eth *eth)
1668 {
1669 	struct airoha_npu *npu;
1670 
1671 	mutex_lock(&flow_offload_mutex);
1672 
1673 	npu = rcu_replace_pointer(eth->npu, NULL,
1674 				  lockdep_is_held(&flow_offload_mutex));
1675 	if (npu) {
1676 		synchronize_rcu();
1677 		npu->ops.ppe_deinit(npu);
1678 		airoha_npu_put(npu);
1679 	}
1680 
1681 	mutex_unlock(&flow_offload_mutex);
1682 
1683 	rhashtable_destroy(&eth->ppe->l2_flows);
1684 	rhashtable_destroy(&eth->flow_table);
1685 	debugfs_remove(eth->ppe->debugfs_dir);
1686 }
1687