xref: /linux/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c (revision 1a9239bb4253f9076b5b4b2a1a4e8d7defd77a95)
1*3fe15c64SLorenzo Bianconi // SPDX-License-Identifier: GPL-2.0-only
2*3fe15c64SLorenzo Bianconi /*
3*3fe15c64SLorenzo Bianconi  * Copyright (c) 2025 AIROHA Inc
4*3fe15c64SLorenzo Bianconi  * Author: Lorenzo Bianconi <lorenzo@kernel.org>
5*3fe15c64SLorenzo Bianconi  */
6*3fe15c64SLorenzo Bianconi 
7*3fe15c64SLorenzo Bianconi #include "airoha_eth.h"
8*3fe15c64SLorenzo Bianconi 
airoha_debugfs_ppe_print_tuple(struct seq_file * m,void * src_addr,void * dest_addr,u16 * src_port,u16 * dest_port,bool ipv6)9*3fe15c64SLorenzo Bianconi static void airoha_debugfs_ppe_print_tuple(struct seq_file *m,
10*3fe15c64SLorenzo Bianconi 					   void *src_addr, void *dest_addr,
11*3fe15c64SLorenzo Bianconi 					   u16 *src_port, u16 *dest_port,
12*3fe15c64SLorenzo Bianconi 					   bool ipv6)
13*3fe15c64SLorenzo Bianconi {
14*3fe15c64SLorenzo Bianconi 	__be32 n_addr[IPV6_ADDR_WORDS];
15*3fe15c64SLorenzo Bianconi 
16*3fe15c64SLorenzo Bianconi 	if (ipv6) {
17*3fe15c64SLorenzo Bianconi 		ipv6_addr_cpu_to_be32(n_addr, src_addr);
18*3fe15c64SLorenzo Bianconi 		seq_printf(m, "%pI6", n_addr);
19*3fe15c64SLorenzo Bianconi 	} else {
20*3fe15c64SLorenzo Bianconi 		seq_printf(m, "%pI4h", src_addr);
21*3fe15c64SLorenzo Bianconi 	}
22*3fe15c64SLorenzo Bianconi 	if (src_port)
23*3fe15c64SLorenzo Bianconi 		seq_printf(m, ":%d", *src_port);
24*3fe15c64SLorenzo Bianconi 
25*3fe15c64SLorenzo Bianconi 	seq_puts(m, "->");
26*3fe15c64SLorenzo Bianconi 
27*3fe15c64SLorenzo Bianconi 	if (ipv6) {
28*3fe15c64SLorenzo Bianconi 		ipv6_addr_cpu_to_be32(n_addr, dest_addr);
29*3fe15c64SLorenzo Bianconi 		seq_printf(m, "%pI6", n_addr);
30*3fe15c64SLorenzo Bianconi 	} else {
31*3fe15c64SLorenzo Bianconi 		seq_printf(m, "%pI4h", dest_addr);
32*3fe15c64SLorenzo Bianconi 	}
33*3fe15c64SLorenzo Bianconi 	if (dest_port)
34*3fe15c64SLorenzo Bianconi 		seq_printf(m, ":%d", *dest_port);
35*3fe15c64SLorenzo Bianconi }
36*3fe15c64SLorenzo Bianconi 
airoha_ppe_debugfs_foe_show(struct seq_file * m,void * private,bool bind)37*3fe15c64SLorenzo Bianconi static int airoha_ppe_debugfs_foe_show(struct seq_file *m, void *private,
38*3fe15c64SLorenzo Bianconi 				       bool bind)
39*3fe15c64SLorenzo Bianconi {
40*3fe15c64SLorenzo Bianconi 	static const char *const ppe_type_str[] = {
41*3fe15c64SLorenzo Bianconi 		[PPE_PKT_TYPE_IPV4_HNAPT] = "IPv4 5T",
42*3fe15c64SLorenzo Bianconi 		[PPE_PKT_TYPE_IPV4_ROUTE] = "IPv4 3T",
43*3fe15c64SLorenzo Bianconi 		[PPE_PKT_TYPE_BRIDGE] = "L2B",
44*3fe15c64SLorenzo Bianconi 		[PPE_PKT_TYPE_IPV4_DSLITE] = "DS-LITE",
45*3fe15c64SLorenzo Bianconi 		[PPE_PKT_TYPE_IPV6_ROUTE_3T] = "IPv6 3T",
46*3fe15c64SLorenzo Bianconi 		[PPE_PKT_TYPE_IPV6_ROUTE_5T] = "IPv6 5T",
47*3fe15c64SLorenzo Bianconi 		[PPE_PKT_TYPE_IPV6_6RD] = "6RD",
48*3fe15c64SLorenzo Bianconi 	};
49*3fe15c64SLorenzo Bianconi 	static const char *const ppe_state_str[] = {
50*3fe15c64SLorenzo Bianconi 		[AIROHA_FOE_STATE_INVALID] = "INV",
51*3fe15c64SLorenzo Bianconi 		[AIROHA_FOE_STATE_UNBIND] = "UNB",
52*3fe15c64SLorenzo Bianconi 		[AIROHA_FOE_STATE_BIND] = "BND",
53*3fe15c64SLorenzo Bianconi 		[AIROHA_FOE_STATE_FIN] = "FIN",
54*3fe15c64SLorenzo Bianconi 	};
55*3fe15c64SLorenzo Bianconi 	struct airoha_ppe *ppe = m->private;
56*3fe15c64SLorenzo Bianconi 	int i;
57*3fe15c64SLorenzo Bianconi 
58*3fe15c64SLorenzo Bianconi 	for (i = 0; i < PPE_NUM_ENTRIES; i++) {
59*3fe15c64SLorenzo Bianconi 		const char *state_str, *type_str = "UNKNOWN";
60*3fe15c64SLorenzo Bianconi 		void *src_addr = NULL, *dest_addr = NULL;
61*3fe15c64SLorenzo Bianconi 		u16 *src_port = NULL, *dest_port = NULL;
62*3fe15c64SLorenzo Bianconi 		struct airoha_foe_mac_info_common *l2;
63*3fe15c64SLorenzo Bianconi 		unsigned char h_source[ETH_ALEN] = {};
64*3fe15c64SLorenzo Bianconi 		unsigned char h_dest[ETH_ALEN];
65*3fe15c64SLorenzo Bianconi 		struct airoha_foe_entry *hwe;
66*3fe15c64SLorenzo Bianconi 		u32 type, state, ib2, data;
67*3fe15c64SLorenzo Bianconi 		bool ipv6 = false;
68*3fe15c64SLorenzo Bianconi 
69*3fe15c64SLorenzo Bianconi 		hwe = airoha_ppe_foe_get_entry(ppe, i);
70*3fe15c64SLorenzo Bianconi 		if (!hwe)
71*3fe15c64SLorenzo Bianconi 			continue;
72*3fe15c64SLorenzo Bianconi 
73*3fe15c64SLorenzo Bianconi 		state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, hwe->ib1);
74*3fe15c64SLorenzo Bianconi 		if (!state)
75*3fe15c64SLorenzo Bianconi 			continue;
76*3fe15c64SLorenzo Bianconi 
77*3fe15c64SLorenzo Bianconi 		if (bind && state != AIROHA_FOE_STATE_BIND)
78*3fe15c64SLorenzo Bianconi 			continue;
79*3fe15c64SLorenzo Bianconi 
80*3fe15c64SLorenzo Bianconi 		state_str = ppe_state_str[state % ARRAY_SIZE(ppe_state_str)];
81*3fe15c64SLorenzo Bianconi 		type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1);
82*3fe15c64SLorenzo Bianconi 		if (type < ARRAY_SIZE(ppe_type_str) && ppe_type_str[type])
83*3fe15c64SLorenzo Bianconi 			type_str = ppe_type_str[type];
84*3fe15c64SLorenzo Bianconi 
85*3fe15c64SLorenzo Bianconi 		seq_printf(m, "%05x %s %7s", i, state_str, type_str);
86*3fe15c64SLorenzo Bianconi 
87*3fe15c64SLorenzo Bianconi 		switch (type) {
88*3fe15c64SLorenzo Bianconi 		case PPE_PKT_TYPE_IPV4_HNAPT:
89*3fe15c64SLorenzo Bianconi 		case PPE_PKT_TYPE_IPV4_DSLITE:
90*3fe15c64SLorenzo Bianconi 			src_port = &hwe->ipv4.orig_tuple.src_port;
91*3fe15c64SLorenzo Bianconi 			dest_port = &hwe->ipv4.orig_tuple.dest_port;
92*3fe15c64SLorenzo Bianconi 			fallthrough;
93*3fe15c64SLorenzo Bianconi 		case PPE_PKT_TYPE_IPV4_ROUTE:
94*3fe15c64SLorenzo Bianconi 			src_addr = &hwe->ipv4.orig_tuple.src_ip;
95*3fe15c64SLorenzo Bianconi 			dest_addr = &hwe->ipv4.orig_tuple.dest_ip;
96*3fe15c64SLorenzo Bianconi 			break;
97*3fe15c64SLorenzo Bianconi 		case PPE_PKT_TYPE_IPV6_ROUTE_5T:
98*3fe15c64SLorenzo Bianconi 			src_port = &hwe->ipv6.src_port;
99*3fe15c64SLorenzo Bianconi 			dest_port = &hwe->ipv6.dest_port;
100*3fe15c64SLorenzo Bianconi 			fallthrough;
101*3fe15c64SLorenzo Bianconi 		case PPE_PKT_TYPE_IPV6_ROUTE_3T:
102*3fe15c64SLorenzo Bianconi 		case PPE_PKT_TYPE_IPV6_6RD:
103*3fe15c64SLorenzo Bianconi 			src_addr = &hwe->ipv6.src_ip;
104*3fe15c64SLorenzo Bianconi 			dest_addr = &hwe->ipv6.dest_ip;
105*3fe15c64SLorenzo Bianconi 			ipv6 = true;
106*3fe15c64SLorenzo Bianconi 			break;
107*3fe15c64SLorenzo Bianconi 		default:
108*3fe15c64SLorenzo Bianconi 			break;
109*3fe15c64SLorenzo Bianconi 		}
110*3fe15c64SLorenzo Bianconi 
111*3fe15c64SLorenzo Bianconi 		if (src_addr && dest_addr) {
112*3fe15c64SLorenzo Bianconi 			seq_puts(m, " orig=");
113*3fe15c64SLorenzo Bianconi 			airoha_debugfs_ppe_print_tuple(m, src_addr, dest_addr,
114*3fe15c64SLorenzo Bianconi 						       src_port, dest_port, ipv6);
115*3fe15c64SLorenzo Bianconi 		}
116*3fe15c64SLorenzo Bianconi 
117*3fe15c64SLorenzo Bianconi 		switch (type) {
118*3fe15c64SLorenzo Bianconi 		case PPE_PKT_TYPE_IPV4_HNAPT:
119*3fe15c64SLorenzo Bianconi 		case PPE_PKT_TYPE_IPV4_DSLITE:
120*3fe15c64SLorenzo Bianconi 			src_port = &hwe->ipv4.new_tuple.src_port;
121*3fe15c64SLorenzo Bianconi 			dest_port = &hwe->ipv4.new_tuple.dest_port;
122*3fe15c64SLorenzo Bianconi 			fallthrough;
123*3fe15c64SLorenzo Bianconi 		case PPE_PKT_TYPE_IPV4_ROUTE:
124*3fe15c64SLorenzo Bianconi 			src_addr = &hwe->ipv4.new_tuple.src_ip;
125*3fe15c64SLorenzo Bianconi 			dest_addr = &hwe->ipv4.new_tuple.dest_ip;
126*3fe15c64SLorenzo Bianconi 			seq_puts(m, " new=");
127*3fe15c64SLorenzo Bianconi 			airoha_debugfs_ppe_print_tuple(m, src_addr, dest_addr,
128*3fe15c64SLorenzo Bianconi 						       src_port, dest_port,
129*3fe15c64SLorenzo Bianconi 						       ipv6);
130*3fe15c64SLorenzo Bianconi 			break;
131*3fe15c64SLorenzo Bianconi 		default:
132*3fe15c64SLorenzo Bianconi 			break;
133*3fe15c64SLorenzo Bianconi 		}
134*3fe15c64SLorenzo Bianconi 
135*3fe15c64SLorenzo Bianconi 		if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) {
136*3fe15c64SLorenzo Bianconi 			data = hwe->ipv6.data;
137*3fe15c64SLorenzo Bianconi 			ib2 = hwe->ipv6.ib2;
138*3fe15c64SLorenzo Bianconi 			l2 = &hwe->ipv6.l2;
139*3fe15c64SLorenzo Bianconi 		} else {
140*3fe15c64SLorenzo Bianconi 			data = hwe->ipv4.data;
141*3fe15c64SLorenzo Bianconi 			ib2 = hwe->ipv4.ib2;
142*3fe15c64SLorenzo Bianconi 			l2 = &hwe->ipv4.l2.common;
143*3fe15c64SLorenzo Bianconi 			*((__be16 *)&h_source[4]) =
144*3fe15c64SLorenzo Bianconi 				cpu_to_be16(hwe->ipv4.l2.src_mac_lo);
145*3fe15c64SLorenzo Bianconi 		}
146*3fe15c64SLorenzo Bianconi 
147*3fe15c64SLorenzo Bianconi 		*((__be32 *)h_dest) = cpu_to_be32(l2->dest_mac_hi);
148*3fe15c64SLorenzo Bianconi 		*((__be16 *)&h_dest[4]) = cpu_to_be16(l2->dest_mac_lo);
149*3fe15c64SLorenzo Bianconi 		*((__be32 *)h_source) = cpu_to_be32(l2->src_mac_hi);
150*3fe15c64SLorenzo Bianconi 
151*3fe15c64SLorenzo Bianconi 		seq_printf(m, " eth=%pM->%pM etype=%04x data=%08x"
152*3fe15c64SLorenzo Bianconi 			      " vlan=%d,%d ib1=%08x ib2=%08x\n",
153*3fe15c64SLorenzo Bianconi 			   h_source, h_dest, l2->etype, data,
154*3fe15c64SLorenzo Bianconi 			   l2->vlan1, l2->vlan2, hwe->ib1, ib2);
155*3fe15c64SLorenzo Bianconi 	}
156*3fe15c64SLorenzo Bianconi 
157*3fe15c64SLorenzo Bianconi 	return 0;
158*3fe15c64SLorenzo Bianconi }
159*3fe15c64SLorenzo Bianconi 
airoha_ppe_debugfs_foe_all_show(struct seq_file * m,void * private)160*3fe15c64SLorenzo Bianconi static int airoha_ppe_debugfs_foe_all_show(struct seq_file *m, void *private)
161*3fe15c64SLorenzo Bianconi {
162*3fe15c64SLorenzo Bianconi 	return airoha_ppe_debugfs_foe_show(m, private, false);
163*3fe15c64SLorenzo Bianconi }
164*3fe15c64SLorenzo Bianconi DEFINE_SHOW_ATTRIBUTE(airoha_ppe_debugfs_foe_all);
165*3fe15c64SLorenzo Bianconi 
airoha_ppe_debugfs_foe_bind_show(struct seq_file * m,void * private)166*3fe15c64SLorenzo Bianconi static int airoha_ppe_debugfs_foe_bind_show(struct seq_file *m, void *private)
167*3fe15c64SLorenzo Bianconi {
168*3fe15c64SLorenzo Bianconi 	return airoha_ppe_debugfs_foe_show(m, private, true);
169*3fe15c64SLorenzo Bianconi }
170*3fe15c64SLorenzo Bianconi DEFINE_SHOW_ATTRIBUTE(airoha_ppe_debugfs_foe_bind);
171*3fe15c64SLorenzo Bianconi 
airoha_ppe_debugfs_init(struct airoha_ppe * ppe)172*3fe15c64SLorenzo Bianconi int airoha_ppe_debugfs_init(struct airoha_ppe *ppe)
173*3fe15c64SLorenzo Bianconi {
174*3fe15c64SLorenzo Bianconi 	ppe->debugfs_dir = debugfs_create_dir("ppe", NULL);
175*3fe15c64SLorenzo Bianconi 	debugfs_create_file("entries", 0444, ppe->debugfs_dir, ppe,
176*3fe15c64SLorenzo Bianconi 			    &airoha_ppe_debugfs_foe_all_fops);
177*3fe15c64SLorenzo Bianconi 	debugfs_create_file("bind", 0444, ppe->debugfs_dir, ppe,
178*3fe15c64SLorenzo Bianconi 			    &airoha_ppe_debugfs_foe_bind_fops);
179*3fe15c64SLorenzo Bianconi 
180*3fe15c64SLorenzo Bianconi 	return 0;
181*3fe15c64SLorenzo Bianconi }
182