1403f69bbSGerhard Engleder // SPDX-License-Identifier: GPL-2.0
2403f69bbSGerhard Engleder /* Copyright (C) 2021 Gerhard Engleder <gerhard@engleder-embedded.com> */
3403f69bbSGerhard Engleder 
4403f69bbSGerhard Engleder #include "tsnep.h"
5403f69bbSGerhard Engleder 
6403f69bbSGerhard Engleder #include <net/pkt_sched.h>
7403f69bbSGerhard Engleder 
8403f69bbSGerhard Engleder enum tsnep_test {
9403f69bbSGerhard Engleder 	TSNEP_TEST_ENABLE = 0,
10403f69bbSGerhard Engleder 	TSNEP_TEST_TAPRIO,
11403f69bbSGerhard Engleder 	TSNEP_TEST_TAPRIO_CHANGE,
12403f69bbSGerhard Engleder 	TSNEP_TEST_TAPRIO_EXTENSION,
13403f69bbSGerhard Engleder };
14403f69bbSGerhard Engleder 
15403f69bbSGerhard Engleder static const char tsnep_test_strings[][ETH_GSTRING_LEN] = {
16403f69bbSGerhard Engleder 	"Enable timeout        (offline)",
17403f69bbSGerhard Engleder 	"TAPRIO                (offline)",
18403f69bbSGerhard Engleder 	"TAPRIO change         (offline)",
19403f69bbSGerhard Engleder 	"TAPRIO extension      (offline)",
20403f69bbSGerhard Engleder };
21403f69bbSGerhard Engleder 
22403f69bbSGerhard Engleder #define TSNEP_TEST_COUNT (sizeof(tsnep_test_strings) / ETH_GSTRING_LEN)
23403f69bbSGerhard Engleder 
enable_gc_timeout(struct tsnep_adapter * adapter)24403f69bbSGerhard Engleder static bool enable_gc_timeout(struct tsnep_adapter *adapter)
25403f69bbSGerhard Engleder {
26403f69bbSGerhard Engleder 	iowrite8(TSNEP_GC_ENABLE_TIMEOUT, adapter->addr + TSNEP_GC);
27403f69bbSGerhard Engleder 	if (!(ioread32(adapter->addr + TSNEP_GC) & TSNEP_GC_TIMEOUT_ACTIVE))
28403f69bbSGerhard Engleder 		return false;
29403f69bbSGerhard Engleder 
30403f69bbSGerhard Engleder 	return true;
31403f69bbSGerhard Engleder }
32403f69bbSGerhard Engleder 
gc_timeout_signaled(struct tsnep_adapter * adapter)33403f69bbSGerhard Engleder static bool gc_timeout_signaled(struct tsnep_adapter *adapter)
34403f69bbSGerhard Engleder {
35403f69bbSGerhard Engleder 	if (ioread32(adapter->addr + TSNEP_GC) & TSNEP_GC_TIMEOUT_SIGNAL)
36403f69bbSGerhard Engleder 		return true;
37403f69bbSGerhard Engleder 
38403f69bbSGerhard Engleder 	return false;
39403f69bbSGerhard Engleder }
40403f69bbSGerhard Engleder 
ack_gc_timeout(struct tsnep_adapter * adapter)41403f69bbSGerhard Engleder static bool ack_gc_timeout(struct tsnep_adapter *adapter)
42403f69bbSGerhard Engleder {
43403f69bbSGerhard Engleder 	iowrite8(TSNEP_GC_ENABLE_TIMEOUT, adapter->addr + TSNEP_GC);
44403f69bbSGerhard Engleder 	if (ioread32(adapter->addr + TSNEP_GC) &
45403f69bbSGerhard Engleder 	    (TSNEP_GC_TIMEOUT_ACTIVE | TSNEP_GC_TIMEOUT_SIGNAL))
46403f69bbSGerhard Engleder 		return false;
47403f69bbSGerhard Engleder 	return true;
48403f69bbSGerhard Engleder }
49403f69bbSGerhard Engleder 
enable_gc(struct tsnep_adapter * adapter,bool a)50403f69bbSGerhard Engleder static bool enable_gc(struct tsnep_adapter *adapter, bool a)
51403f69bbSGerhard Engleder {
52403f69bbSGerhard Engleder 	u8 enable;
53403f69bbSGerhard Engleder 	u8 active;
54403f69bbSGerhard Engleder 
55403f69bbSGerhard Engleder 	if (a) {
56403f69bbSGerhard Engleder 		enable = TSNEP_GC_ENABLE_A;
57403f69bbSGerhard Engleder 		active = TSNEP_GC_ACTIVE_A;
58403f69bbSGerhard Engleder 	} else {
59403f69bbSGerhard Engleder 		enable = TSNEP_GC_ENABLE_B;
60403f69bbSGerhard Engleder 		active = TSNEP_GC_ACTIVE_B;
61403f69bbSGerhard Engleder 	}
62403f69bbSGerhard Engleder 
63403f69bbSGerhard Engleder 	iowrite8(enable, adapter->addr + TSNEP_GC);
64403f69bbSGerhard Engleder 	if (!(ioread32(adapter->addr + TSNEP_GC) & active))
65403f69bbSGerhard Engleder 		return false;
66403f69bbSGerhard Engleder 
67403f69bbSGerhard Engleder 	return true;
68403f69bbSGerhard Engleder }
69403f69bbSGerhard Engleder 
disable_gc(struct tsnep_adapter * adapter)70403f69bbSGerhard Engleder static bool disable_gc(struct tsnep_adapter *adapter)
71403f69bbSGerhard Engleder {
72403f69bbSGerhard Engleder 	iowrite8(TSNEP_GC_DISABLE, adapter->addr + TSNEP_GC);
73403f69bbSGerhard Engleder 	if (ioread32(adapter->addr + TSNEP_GC) &
74403f69bbSGerhard Engleder 	    (TSNEP_GC_ACTIVE_A | TSNEP_GC_ACTIVE_B))
75403f69bbSGerhard Engleder 		return false;
76403f69bbSGerhard Engleder 
77403f69bbSGerhard Engleder 	return true;
78403f69bbSGerhard Engleder }
79403f69bbSGerhard Engleder 
gc_delayed_enable(struct tsnep_adapter * adapter,bool a,int delay)80403f69bbSGerhard Engleder static bool gc_delayed_enable(struct tsnep_adapter *adapter, bool a, int delay)
81403f69bbSGerhard Engleder {
82403f69bbSGerhard Engleder 	u64 before, after;
83403f69bbSGerhard Engleder 	u32 time;
84403f69bbSGerhard Engleder 	bool enabled;
85403f69bbSGerhard Engleder 
86403f69bbSGerhard Engleder 	if (!disable_gc(adapter))
87403f69bbSGerhard Engleder 		return false;
88403f69bbSGerhard Engleder 
89403f69bbSGerhard Engleder 	before = ktime_get_ns();
90403f69bbSGerhard Engleder 
91403f69bbSGerhard Engleder 	if (!enable_gc_timeout(adapter))
92403f69bbSGerhard Engleder 		return false;
93403f69bbSGerhard Engleder 
94403f69bbSGerhard Engleder 	/* for start time after timeout, the timeout can guarantee, that enable
95403f69bbSGerhard Engleder 	 * is blocked if too late
96403f69bbSGerhard Engleder 	 */
97403f69bbSGerhard Engleder 	time = ioread32(adapter->addr + ECM_SYSTEM_TIME_LOW);
98403f69bbSGerhard Engleder 	time += TSNEP_GC_TIMEOUT;
99403f69bbSGerhard Engleder 	iowrite32(time, adapter->addr + TSNEP_GC_TIME);
100403f69bbSGerhard Engleder 
101403f69bbSGerhard Engleder 	ndelay(delay);
102403f69bbSGerhard Engleder 
103403f69bbSGerhard Engleder 	enabled = enable_gc(adapter, a);
104403f69bbSGerhard Engleder 	after = ktime_get_ns();
105403f69bbSGerhard Engleder 
106403f69bbSGerhard Engleder 	if (delay > TSNEP_GC_TIMEOUT) {
107403f69bbSGerhard Engleder 		/* timeout must have blocked enable */
108403f69bbSGerhard Engleder 		if (enabled)
109403f69bbSGerhard Engleder 			return false;
110403f69bbSGerhard Engleder 	} else if ((after - before) < TSNEP_GC_TIMEOUT * 14 / 16) {
111403f69bbSGerhard Engleder 		/* timeout must not have blocked enable */
112403f69bbSGerhard Engleder 		if (!enabled)
113403f69bbSGerhard Engleder 			return false;
114403f69bbSGerhard Engleder 	}
115403f69bbSGerhard Engleder 
116403f69bbSGerhard Engleder 	if (enabled) {
117403f69bbSGerhard Engleder 		if (gc_timeout_signaled(adapter))
118403f69bbSGerhard Engleder 			return false;
119403f69bbSGerhard Engleder 	} else {
120403f69bbSGerhard Engleder 		if (!gc_timeout_signaled(adapter))
121403f69bbSGerhard Engleder 			return false;
122403f69bbSGerhard Engleder 		if (!ack_gc_timeout(adapter))
123403f69bbSGerhard Engleder 			return false;
124403f69bbSGerhard Engleder 	}
125403f69bbSGerhard Engleder 
126403f69bbSGerhard Engleder 	if (!disable_gc(adapter))
127403f69bbSGerhard Engleder 		return false;
128403f69bbSGerhard Engleder 
129403f69bbSGerhard Engleder 	return true;
130403f69bbSGerhard Engleder }
131403f69bbSGerhard Engleder 
tsnep_test_gc_enable(struct tsnep_adapter * adapter)132403f69bbSGerhard Engleder static bool tsnep_test_gc_enable(struct tsnep_adapter *adapter)
133403f69bbSGerhard Engleder {
134403f69bbSGerhard Engleder 	int i;
135403f69bbSGerhard Engleder 
136403f69bbSGerhard Engleder 	iowrite32(0x80000001, adapter->addr + TSNEP_GCL_A + 0);
137403f69bbSGerhard Engleder 	iowrite32(100000, adapter->addr + TSNEP_GCL_A + 4);
138403f69bbSGerhard Engleder 
139403f69bbSGerhard Engleder 	for (i = 0; i < 200000; i += 100) {
140403f69bbSGerhard Engleder 		if (!gc_delayed_enable(adapter, true, i))
141403f69bbSGerhard Engleder 			return false;
142403f69bbSGerhard Engleder 	}
143403f69bbSGerhard Engleder 
144403f69bbSGerhard Engleder 	iowrite32(0x80000001, adapter->addr + TSNEP_GCL_B + 0);
145403f69bbSGerhard Engleder 	iowrite32(100000, adapter->addr + TSNEP_GCL_B + 4);
146403f69bbSGerhard Engleder 
147403f69bbSGerhard Engleder 	for (i = 0; i < 200000; i += 100) {
148403f69bbSGerhard Engleder 		if (!gc_delayed_enable(adapter, false, i))
149403f69bbSGerhard Engleder 			return false;
150403f69bbSGerhard Engleder 	}
151403f69bbSGerhard Engleder 
152403f69bbSGerhard Engleder 	return true;
153403f69bbSGerhard Engleder }
154403f69bbSGerhard Engleder 
delay_base_time(struct tsnep_adapter * adapter,struct tc_taprio_qopt_offload * qopt,s64 ms)155403f69bbSGerhard Engleder static void delay_base_time(struct tsnep_adapter *adapter,
156403f69bbSGerhard Engleder 			    struct tc_taprio_qopt_offload *qopt, s64 ms)
157403f69bbSGerhard Engleder {
158403f69bbSGerhard Engleder 	u64 system_time;
159403f69bbSGerhard Engleder 	u64 base_time = ktime_to_ns(qopt->base_time);
160403f69bbSGerhard Engleder 	u64 n;
161403f69bbSGerhard Engleder 
162403f69bbSGerhard Engleder 	tsnep_get_system_time(adapter, &system_time);
163403f69bbSGerhard Engleder 	system_time += ms * 1000000;
164403f69bbSGerhard Engleder 	n = div64_u64(system_time - base_time, qopt->cycle_time);
165403f69bbSGerhard Engleder 
166403f69bbSGerhard Engleder 	qopt->base_time = ktime_add_ns(qopt->base_time,
167403f69bbSGerhard Engleder 				       (n + 1) * qopt->cycle_time);
168403f69bbSGerhard Engleder }
169403f69bbSGerhard Engleder 
get_gate_state(struct tsnep_adapter * adapter,u32 * gc,u32 * gc_time,u64 * system_time)170403f69bbSGerhard Engleder static void get_gate_state(struct tsnep_adapter *adapter, u32 *gc, u32 *gc_time,
171403f69bbSGerhard Engleder 			   u64 *system_time)
172403f69bbSGerhard Engleder {
173403f69bbSGerhard Engleder 	u32 time_high_before;
174403f69bbSGerhard Engleder 	u32 time_low;
175403f69bbSGerhard Engleder 	u32 time_high;
176403f69bbSGerhard Engleder 	u32 gc_time_before;
177403f69bbSGerhard Engleder 
178403f69bbSGerhard Engleder 	time_high = ioread32(adapter->addr + ECM_SYSTEM_TIME_HIGH);
179403f69bbSGerhard Engleder 	*gc_time = ioread32(adapter->addr + TSNEP_GC_TIME);
180403f69bbSGerhard Engleder 	do {
181403f69bbSGerhard Engleder 		time_low = ioread32(adapter->addr + ECM_SYSTEM_TIME_LOW);
182403f69bbSGerhard Engleder 		*gc = ioread32(adapter->addr + TSNEP_GC);
183403f69bbSGerhard Engleder 
184403f69bbSGerhard Engleder 		gc_time_before = *gc_time;
185403f69bbSGerhard Engleder 		*gc_time = ioread32(adapter->addr + TSNEP_GC_TIME);
186403f69bbSGerhard Engleder 		time_high_before = time_high;
187403f69bbSGerhard Engleder 		time_high = ioread32(adapter->addr + ECM_SYSTEM_TIME_HIGH);
188403f69bbSGerhard Engleder 	} while ((time_high != time_high_before) ||
189403f69bbSGerhard Engleder 		 (*gc_time != gc_time_before));
190403f69bbSGerhard Engleder 
191403f69bbSGerhard Engleder 	*system_time = (((u64)time_high) << 32) | ((u64)time_low);
192403f69bbSGerhard Engleder }
193403f69bbSGerhard Engleder 
get_operation(struct tsnep_gcl * gcl,u64 system_time,u64 * next)194403f69bbSGerhard Engleder static int get_operation(struct tsnep_gcl *gcl, u64 system_time, u64 *next)
195403f69bbSGerhard Engleder {
196403f69bbSGerhard Engleder 	u64 n = div64_u64(system_time - gcl->base_time, gcl->cycle_time);
197403f69bbSGerhard Engleder 	u64 cycle_start = gcl->base_time + gcl->cycle_time * n;
198403f69bbSGerhard Engleder 	int i;
199403f69bbSGerhard Engleder 
200403f69bbSGerhard Engleder 	*next = cycle_start;
201403f69bbSGerhard Engleder 	for (i = 0; i < gcl->count; i++) {
202403f69bbSGerhard Engleder 		*next += gcl->operation[i].interval;
203403f69bbSGerhard Engleder 		if (*next > system_time)
204403f69bbSGerhard Engleder 			break;
205403f69bbSGerhard Engleder 	}
206403f69bbSGerhard Engleder 
207403f69bbSGerhard Engleder 	return i;
208403f69bbSGerhard Engleder }
209403f69bbSGerhard Engleder 
check_gate(struct tsnep_adapter * adapter)210403f69bbSGerhard Engleder static bool check_gate(struct tsnep_adapter *adapter)
211403f69bbSGerhard Engleder {
212403f69bbSGerhard Engleder 	u32 gc_time;
213403f69bbSGerhard Engleder 	u32 gc;
214403f69bbSGerhard Engleder 	u64 system_time;
215403f69bbSGerhard Engleder 	struct tsnep_gcl *curr;
216403f69bbSGerhard Engleder 	struct tsnep_gcl *prev;
217403f69bbSGerhard Engleder 	u64 next_time;
218403f69bbSGerhard Engleder 	u8 gate_open;
219403f69bbSGerhard Engleder 	u8 next_gate_open;
220403f69bbSGerhard Engleder 
221403f69bbSGerhard Engleder 	get_gate_state(adapter, &gc, &gc_time, &system_time);
222403f69bbSGerhard Engleder 
223403f69bbSGerhard Engleder 	if (gc & TSNEP_GC_ACTIVE_A) {
224403f69bbSGerhard Engleder 		curr = &adapter->gcl[0];
225403f69bbSGerhard Engleder 		prev = &adapter->gcl[1];
226403f69bbSGerhard Engleder 	} else if (gc & TSNEP_GC_ACTIVE_B) {
227403f69bbSGerhard Engleder 		curr = &adapter->gcl[1];
228403f69bbSGerhard Engleder 		prev = &adapter->gcl[0];
229403f69bbSGerhard Engleder 	} else {
230403f69bbSGerhard Engleder 		return false;
231403f69bbSGerhard Engleder 	}
232403f69bbSGerhard Engleder 	if (curr->start_time <= system_time) {
233403f69bbSGerhard Engleder 		/* GCL is already active */
234403f69bbSGerhard Engleder 		int index;
235403f69bbSGerhard Engleder 
236403f69bbSGerhard Engleder 		index = get_operation(curr, system_time, &next_time);
237403f69bbSGerhard Engleder 		gate_open = curr->operation[index].properties & TSNEP_GCL_MASK;
238403f69bbSGerhard Engleder 		if (index == curr->count - 1)
239403f69bbSGerhard Engleder 			index = 0;
240403f69bbSGerhard Engleder 		else
241403f69bbSGerhard Engleder 			index++;
242403f69bbSGerhard Engleder 		next_gate_open =
243403f69bbSGerhard Engleder 			curr->operation[index].properties & TSNEP_GCL_MASK;
244403f69bbSGerhard Engleder 	} else if (curr->change) {
245403f69bbSGerhard Engleder 		/* operation of previous GCL is active */
246403f69bbSGerhard Engleder 		int index;
247403f69bbSGerhard Engleder 		u64 start_before;
248403f69bbSGerhard Engleder 		u64 n;
249403f69bbSGerhard Engleder 
250403f69bbSGerhard Engleder 		index = get_operation(prev, system_time, &next_time);
251403f69bbSGerhard Engleder 		next_time = curr->start_time;
252403f69bbSGerhard Engleder 		start_before = prev->base_time;
253403f69bbSGerhard Engleder 		n = div64_u64(curr->start_time - start_before,
254403f69bbSGerhard Engleder 			      prev->cycle_time);
255403f69bbSGerhard Engleder 		start_before += n * prev->cycle_time;
256403f69bbSGerhard Engleder 		if (curr->start_time == start_before)
257403f69bbSGerhard Engleder 			start_before -= prev->cycle_time;
258403f69bbSGerhard Engleder 		if (((start_before + prev->cycle_time_extension) >=
259403f69bbSGerhard Engleder 		     curr->start_time) &&
260403f69bbSGerhard Engleder 		    (curr->start_time - prev->cycle_time_extension <=
261403f69bbSGerhard Engleder 		     system_time)) {
262403f69bbSGerhard Engleder 			/* extend */
263403f69bbSGerhard Engleder 			index = prev->count - 1;
264403f69bbSGerhard Engleder 		}
265403f69bbSGerhard Engleder 		gate_open = prev->operation[index].properties & TSNEP_GCL_MASK;
266403f69bbSGerhard Engleder 		next_gate_open =
267403f69bbSGerhard Engleder 			curr->operation[0].properties & TSNEP_GCL_MASK;
268403f69bbSGerhard Engleder 	} else {
269403f69bbSGerhard Engleder 		/* GCL is waiting for start */
270403f69bbSGerhard Engleder 		next_time = curr->start_time;
271403f69bbSGerhard Engleder 		gate_open = 0xFF;
272403f69bbSGerhard Engleder 		next_gate_open = curr->operation[0].properties & TSNEP_GCL_MASK;
273403f69bbSGerhard Engleder 	}
274403f69bbSGerhard Engleder 
275403f69bbSGerhard Engleder 	if (gc_time != (next_time & 0xFFFFFFFF)) {
276403f69bbSGerhard Engleder 		dev_err(&adapter->pdev->dev, "gate control time 0x%x!=0x%llx\n",
277403f69bbSGerhard Engleder 			gc_time, next_time);
278403f69bbSGerhard Engleder 		return false;
279403f69bbSGerhard Engleder 	}
280403f69bbSGerhard Engleder 	if (((gc & TSNEP_GC_OPEN) >> TSNEP_GC_OPEN_SHIFT) != gate_open) {
281403f69bbSGerhard Engleder 		dev_err(&adapter->pdev->dev,
282403f69bbSGerhard Engleder 			"gate control open 0x%02x!=0x%02x\n",
283403f69bbSGerhard Engleder 			((gc & TSNEP_GC_OPEN) >> TSNEP_GC_OPEN_SHIFT),
284403f69bbSGerhard Engleder 			gate_open);
285403f69bbSGerhard Engleder 		return false;
286403f69bbSGerhard Engleder 	}
287403f69bbSGerhard Engleder 	if (((gc & TSNEP_GC_NEXT_OPEN) >> TSNEP_GC_NEXT_OPEN_SHIFT) !=
288403f69bbSGerhard Engleder 	    next_gate_open) {
289403f69bbSGerhard Engleder 		dev_err(&adapter->pdev->dev,
290403f69bbSGerhard Engleder 			"gate control next open 0x%02x!=0x%02x\n",
291403f69bbSGerhard Engleder 			((gc & TSNEP_GC_NEXT_OPEN) >> TSNEP_GC_NEXT_OPEN_SHIFT),
292403f69bbSGerhard Engleder 			next_gate_open);
293403f69bbSGerhard Engleder 		return false;
294403f69bbSGerhard Engleder 	}
295403f69bbSGerhard Engleder 
296403f69bbSGerhard Engleder 	return true;
297403f69bbSGerhard Engleder }
298403f69bbSGerhard Engleder 
check_gate_duration(struct tsnep_adapter * adapter,s64 ms)299403f69bbSGerhard Engleder static bool check_gate_duration(struct tsnep_adapter *adapter, s64 ms)
300403f69bbSGerhard Engleder {
301403f69bbSGerhard Engleder 	ktime_t start = ktime_get();
302403f69bbSGerhard Engleder 
303403f69bbSGerhard Engleder 	do {
304403f69bbSGerhard Engleder 		if (!check_gate(adapter))
305403f69bbSGerhard Engleder 			return false;
306403f69bbSGerhard Engleder 	} while (ktime_ms_delta(ktime_get(), start) < ms);
307403f69bbSGerhard Engleder 
308403f69bbSGerhard Engleder 	return true;
309403f69bbSGerhard Engleder }
310403f69bbSGerhard Engleder 
enable_check_taprio(struct tsnep_adapter * adapter,struct tc_taprio_qopt_offload * qopt,s64 ms)311403f69bbSGerhard Engleder static bool enable_check_taprio(struct tsnep_adapter *adapter,
312403f69bbSGerhard Engleder 				struct tc_taprio_qopt_offload *qopt, s64 ms)
313403f69bbSGerhard Engleder {
314403f69bbSGerhard Engleder 	int retval;
315403f69bbSGerhard Engleder 
316403f69bbSGerhard Engleder 	retval = tsnep_tc_setup(adapter->netdev, TC_SETUP_QDISC_TAPRIO, qopt);
317403f69bbSGerhard Engleder 	if (retval)
318403f69bbSGerhard Engleder 		return false;
319403f69bbSGerhard Engleder 
320403f69bbSGerhard Engleder 	if (!check_gate_duration(adapter, ms))
321403f69bbSGerhard Engleder 		return false;
322403f69bbSGerhard Engleder 
323403f69bbSGerhard Engleder 	return true;
324403f69bbSGerhard Engleder }
325403f69bbSGerhard Engleder 
disable_taprio(struct tsnep_adapter * adapter)326403f69bbSGerhard Engleder static bool disable_taprio(struct tsnep_adapter *adapter)
327403f69bbSGerhard Engleder {
328403f69bbSGerhard Engleder 	struct tc_taprio_qopt_offload qopt;
329403f69bbSGerhard Engleder 	int retval;
330403f69bbSGerhard Engleder 
331403f69bbSGerhard Engleder 	memset(&qopt, 0, sizeof(qopt));
332*2d800bc5SVladimir Oltean 	qopt.cmd = TAPRIO_CMD_DESTROY;
333403f69bbSGerhard Engleder 	retval = tsnep_tc_setup(adapter->netdev, TC_SETUP_QDISC_TAPRIO, &qopt);
334403f69bbSGerhard Engleder 	if (retval)
335403f69bbSGerhard Engleder 		return false;
336403f69bbSGerhard Engleder 
337403f69bbSGerhard Engleder 	return true;
338403f69bbSGerhard Engleder }
339403f69bbSGerhard Engleder 
run_taprio(struct tsnep_adapter * adapter,struct tc_taprio_qopt_offload * qopt,s64 ms)340403f69bbSGerhard Engleder static bool run_taprio(struct tsnep_adapter *adapter,
341403f69bbSGerhard Engleder 		       struct tc_taprio_qopt_offload *qopt, s64 ms)
342403f69bbSGerhard Engleder {
343403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, ms))
344403f69bbSGerhard Engleder 		return false;
345403f69bbSGerhard Engleder 
346403f69bbSGerhard Engleder 	if (!disable_taprio(adapter))
347403f69bbSGerhard Engleder 		return false;
348403f69bbSGerhard Engleder 
349403f69bbSGerhard Engleder 	return true;
350403f69bbSGerhard Engleder }
351403f69bbSGerhard Engleder 
tsnep_test_taprio(struct tsnep_adapter * adapter)352403f69bbSGerhard Engleder static bool tsnep_test_taprio(struct tsnep_adapter *adapter)
353403f69bbSGerhard Engleder {
354403f69bbSGerhard Engleder 	struct tc_taprio_qopt_offload *qopt;
355403f69bbSGerhard Engleder 	int i;
356403f69bbSGerhard Engleder 
357403f69bbSGerhard Engleder 	qopt = kzalloc(struct_size(qopt, entries, 255), GFP_KERNEL);
358403f69bbSGerhard Engleder 	if (!qopt)
359403f69bbSGerhard Engleder 		return false;
360403f69bbSGerhard Engleder 	for (i = 0; i < 255; i++)
361403f69bbSGerhard Engleder 		qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES;
362403f69bbSGerhard Engleder 
363*2d800bc5SVladimir Oltean 	qopt->cmd = TAPRIO_CMD_REPLACE;
364403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
365403f69bbSGerhard Engleder 	qopt->cycle_time = 1500000;
366403f69bbSGerhard Engleder 	qopt->cycle_time_extension = 0;
367403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x02;
368403f69bbSGerhard Engleder 	qopt->entries[0].interval = 200000;
369403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x03;
370403f69bbSGerhard Engleder 	qopt->entries[1].interval = 800000;
371403f69bbSGerhard Engleder 	qopt->entries[2].gate_mask = 0x07;
372403f69bbSGerhard Engleder 	qopt->entries[2].interval = 240000;
373403f69bbSGerhard Engleder 	qopt->entries[3].gate_mask = 0x01;
374403f69bbSGerhard Engleder 	qopt->entries[3].interval = 80000;
375403f69bbSGerhard Engleder 	qopt->entries[4].gate_mask = 0x04;
376403f69bbSGerhard Engleder 	qopt->entries[4].interval = 70000;
377403f69bbSGerhard Engleder 	qopt->entries[5].gate_mask = 0x06;
378403f69bbSGerhard Engleder 	qopt->entries[5].interval = 60000;
379403f69bbSGerhard Engleder 	qopt->entries[6].gate_mask = 0x0F;
380403f69bbSGerhard Engleder 	qopt->entries[6].interval = 50000;
381403f69bbSGerhard Engleder 	qopt->num_entries = 7;
382403f69bbSGerhard Engleder 	if (!run_taprio(adapter, qopt, 100))
383403f69bbSGerhard Engleder 		goto failed;
384403f69bbSGerhard Engleder 
385*2d800bc5SVladimir Oltean 	qopt->cmd = TAPRIO_CMD_REPLACE;
386403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
387403f69bbSGerhard Engleder 	qopt->cycle_time = 411854;
388403f69bbSGerhard Engleder 	qopt->cycle_time_extension = 0;
389403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x17;
390403f69bbSGerhard Engleder 	qopt->entries[0].interval = 23842;
391403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x16;
392403f69bbSGerhard Engleder 	qopt->entries[1].interval = 13482;
393403f69bbSGerhard Engleder 	qopt->entries[2].gate_mask = 0x15;
394403f69bbSGerhard Engleder 	qopt->entries[2].interval = 49428;
395403f69bbSGerhard Engleder 	qopt->entries[3].gate_mask = 0x14;
396403f69bbSGerhard Engleder 	qopt->entries[3].interval = 38189;
397403f69bbSGerhard Engleder 	qopt->entries[4].gate_mask = 0x13;
398403f69bbSGerhard Engleder 	qopt->entries[4].interval = 92321;
399403f69bbSGerhard Engleder 	qopt->entries[5].gate_mask = 0x12;
400403f69bbSGerhard Engleder 	qopt->entries[5].interval = 71239;
401403f69bbSGerhard Engleder 	qopt->entries[6].gate_mask = 0x11;
402403f69bbSGerhard Engleder 	qopt->entries[6].interval = 69932;
403403f69bbSGerhard Engleder 	qopt->entries[7].gate_mask = 0x10;
404403f69bbSGerhard Engleder 	qopt->entries[7].interval = 53421;
405403f69bbSGerhard Engleder 	qopt->num_entries = 8;
406403f69bbSGerhard Engleder 	if (!run_taprio(adapter, qopt, 100))
407403f69bbSGerhard Engleder 		goto failed;
408403f69bbSGerhard Engleder 
409*2d800bc5SVladimir Oltean 	qopt->cmd = TAPRIO_CMD_REPLACE;
410403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
411403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 12);
412403f69bbSGerhard Engleder 	qopt->cycle_time = 125000;
413403f69bbSGerhard Engleder 	qopt->cycle_time_extension = 0;
414403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x27;
415403f69bbSGerhard Engleder 	qopt->entries[0].interval = 15000;
416403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x26;
417403f69bbSGerhard Engleder 	qopt->entries[1].interval = 15000;
418403f69bbSGerhard Engleder 	qopt->entries[2].gate_mask = 0x25;
419403f69bbSGerhard Engleder 	qopt->entries[2].interval = 12500;
420403f69bbSGerhard Engleder 	qopt->entries[3].gate_mask = 0x24;
421403f69bbSGerhard Engleder 	qopt->entries[3].interval = 17500;
422403f69bbSGerhard Engleder 	qopt->entries[4].gate_mask = 0x23;
423403f69bbSGerhard Engleder 	qopt->entries[4].interval = 10000;
424403f69bbSGerhard Engleder 	qopt->entries[5].gate_mask = 0x22;
425403f69bbSGerhard Engleder 	qopt->entries[5].interval = 11000;
426403f69bbSGerhard Engleder 	qopt->entries[6].gate_mask = 0x21;
427403f69bbSGerhard Engleder 	qopt->entries[6].interval = 9000;
428403f69bbSGerhard Engleder 	qopt->entries[7].gate_mask = 0x20;
429403f69bbSGerhard Engleder 	qopt->entries[7].interval = 10000;
430403f69bbSGerhard Engleder 	qopt->entries[8].gate_mask = 0x20;
431403f69bbSGerhard Engleder 	qopt->entries[8].interval = 12500;
432403f69bbSGerhard Engleder 	qopt->entries[9].gate_mask = 0x20;
433403f69bbSGerhard Engleder 	qopt->entries[9].interval = 12500;
434403f69bbSGerhard Engleder 	qopt->num_entries = 10;
435403f69bbSGerhard Engleder 	if (!run_taprio(adapter, qopt, 100))
436403f69bbSGerhard Engleder 		goto failed;
437403f69bbSGerhard Engleder 
438403f69bbSGerhard Engleder 	kfree(qopt);
439403f69bbSGerhard Engleder 
440403f69bbSGerhard Engleder 	return true;
441403f69bbSGerhard Engleder 
442403f69bbSGerhard Engleder failed:
443403f69bbSGerhard Engleder 	disable_taprio(adapter);
444403f69bbSGerhard Engleder 	kfree(qopt);
445403f69bbSGerhard Engleder 
446403f69bbSGerhard Engleder 	return false;
447403f69bbSGerhard Engleder }
448403f69bbSGerhard Engleder 
tsnep_test_taprio_change(struct tsnep_adapter * adapter)449403f69bbSGerhard Engleder static bool tsnep_test_taprio_change(struct tsnep_adapter *adapter)
450403f69bbSGerhard Engleder {
451403f69bbSGerhard Engleder 	struct tc_taprio_qopt_offload *qopt;
452403f69bbSGerhard Engleder 	int i;
453403f69bbSGerhard Engleder 
454403f69bbSGerhard Engleder 	qopt = kzalloc(struct_size(qopt, entries, 255), GFP_KERNEL);
455403f69bbSGerhard Engleder 	if (!qopt)
456403f69bbSGerhard Engleder 		return false;
457403f69bbSGerhard Engleder 	for (i = 0; i < 255; i++)
458403f69bbSGerhard Engleder 		qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES;
459403f69bbSGerhard Engleder 
460*2d800bc5SVladimir Oltean 	qopt->cmd = TAPRIO_CMD_REPLACE;
461403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
462403f69bbSGerhard Engleder 	qopt->cycle_time = 100000;
463403f69bbSGerhard Engleder 	qopt->cycle_time_extension = 0;
464403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x30;
465403f69bbSGerhard Engleder 	qopt->entries[0].interval = 20000;
466403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x31;
467403f69bbSGerhard Engleder 	qopt->entries[1].interval = 80000;
468403f69bbSGerhard Engleder 	qopt->num_entries = 2;
469403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
470403f69bbSGerhard Engleder 		goto failed;
471403f69bbSGerhard Engleder 
472403f69bbSGerhard Engleder 	/* change to identical */
473403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
474403f69bbSGerhard Engleder 		goto failed;
475403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 17);
476403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
477403f69bbSGerhard Engleder 		goto failed;
478403f69bbSGerhard Engleder 
479403f69bbSGerhard Engleder 	/* change to same cycle time */
480403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
481403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x42;
482403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x43;
483403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 2);
484403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
485403f69bbSGerhard Engleder 		goto failed;
486403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
487403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x54;
488403f69bbSGerhard Engleder 	qopt->entries[0].interval = 33333;
489403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x55;
490403f69bbSGerhard Engleder 	qopt->entries[1].interval = 66667;
491403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 23);
492403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
493403f69bbSGerhard Engleder 		goto failed;
494403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
495403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x66;
496403f69bbSGerhard Engleder 	qopt->entries[0].interval = 50000;
497403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x67;
498403f69bbSGerhard Engleder 	qopt->entries[1].interval = 25000;
499403f69bbSGerhard Engleder 	qopt->entries[2].gate_mask = 0x68;
500403f69bbSGerhard Engleder 	qopt->entries[2].interval = 25000;
501403f69bbSGerhard Engleder 	qopt->num_entries = 3;
502403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 11);
503403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
504403f69bbSGerhard Engleder 		goto failed;
505403f69bbSGerhard Engleder 
506403f69bbSGerhard Engleder 	/* change to multiple of cycle time */
507403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
508403f69bbSGerhard Engleder 	qopt->cycle_time = 200000;
509403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x79;
510403f69bbSGerhard Engleder 	qopt->entries[0].interval = 50000;
511403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x7A;
512403f69bbSGerhard Engleder 	qopt->entries[1].interval = 150000;
513403f69bbSGerhard Engleder 	qopt->num_entries = 2;
514403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 11);
515403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
516403f69bbSGerhard Engleder 		goto failed;
517403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
518403f69bbSGerhard Engleder 	qopt->cycle_time = 1000000;
519403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x7B;
520403f69bbSGerhard Engleder 	qopt->entries[0].interval = 125000;
521403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x7C;
522403f69bbSGerhard Engleder 	qopt->entries[1].interval = 250000;
523403f69bbSGerhard Engleder 	qopt->entries[2].gate_mask = 0x7D;
524403f69bbSGerhard Engleder 	qopt->entries[2].interval = 375000;
525403f69bbSGerhard Engleder 	qopt->entries[3].gate_mask = 0x7E;
526403f69bbSGerhard Engleder 	qopt->entries[3].interval = 250000;
527403f69bbSGerhard Engleder 	qopt->num_entries = 4;
528403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 3);
529403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
530403f69bbSGerhard Engleder 		goto failed;
531403f69bbSGerhard Engleder 
532403f69bbSGerhard Engleder 	/* change to shorter cycle time */
533403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
534403f69bbSGerhard Engleder 	qopt->cycle_time = 333333;
535403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x8F;
536403f69bbSGerhard Engleder 	qopt->entries[0].interval = 166666;
537403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x80;
538403f69bbSGerhard Engleder 	qopt->entries[1].interval = 166667;
539403f69bbSGerhard Engleder 	qopt->num_entries = 2;
540403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 11);
541403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
542403f69bbSGerhard Engleder 		goto failed;
543403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
544403f69bbSGerhard Engleder 	qopt->cycle_time = 62500;
545403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x81;
546403f69bbSGerhard Engleder 	qopt->entries[0].interval = 31250;
547403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x82;
548403f69bbSGerhard Engleder 	qopt->entries[1].interval = 15625;
549403f69bbSGerhard Engleder 	qopt->entries[2].gate_mask = 0x83;
550403f69bbSGerhard Engleder 	qopt->entries[2].interval = 15625;
551403f69bbSGerhard Engleder 	qopt->num_entries = 3;
552403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 1);
553403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
554403f69bbSGerhard Engleder 		goto failed;
555403f69bbSGerhard Engleder 
556403f69bbSGerhard Engleder 	/* change to longer cycle time */
557403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
558403f69bbSGerhard Engleder 	qopt->cycle_time = 400000;
559403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x84;
560403f69bbSGerhard Engleder 	qopt->entries[0].interval = 100000;
561403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x85;
562403f69bbSGerhard Engleder 	qopt->entries[1].interval = 100000;
563403f69bbSGerhard Engleder 	qopt->entries[2].gate_mask = 0x86;
564403f69bbSGerhard Engleder 	qopt->entries[2].interval = 100000;
565403f69bbSGerhard Engleder 	qopt->entries[3].gate_mask = 0x87;
566403f69bbSGerhard Engleder 	qopt->entries[3].interval = 100000;
567403f69bbSGerhard Engleder 	qopt->num_entries = 4;
568403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 7);
569403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
570403f69bbSGerhard Engleder 		goto failed;
571403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
572403f69bbSGerhard Engleder 	qopt->cycle_time = 1700000;
573403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x88;
574403f69bbSGerhard Engleder 	qopt->entries[0].interval = 200000;
575403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x89;
576403f69bbSGerhard Engleder 	qopt->entries[1].interval = 300000;
577403f69bbSGerhard Engleder 	qopt->entries[2].gate_mask = 0x8A;
578403f69bbSGerhard Engleder 	qopt->entries[2].interval = 600000;
579403f69bbSGerhard Engleder 	qopt->entries[3].gate_mask = 0x8B;
580403f69bbSGerhard Engleder 	qopt->entries[3].interval = 100000;
581403f69bbSGerhard Engleder 	qopt->entries[4].gate_mask = 0x8C;
582403f69bbSGerhard Engleder 	qopt->entries[4].interval = 500000;
583403f69bbSGerhard Engleder 	qopt->num_entries = 5;
584403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 6);
585403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
586403f69bbSGerhard Engleder 		goto failed;
587403f69bbSGerhard Engleder 
588403f69bbSGerhard Engleder 	if (!disable_taprio(adapter))
589403f69bbSGerhard Engleder 		goto failed;
590403f69bbSGerhard Engleder 
591403f69bbSGerhard Engleder 	kfree(qopt);
592403f69bbSGerhard Engleder 
593403f69bbSGerhard Engleder 	return true;
594403f69bbSGerhard Engleder 
595403f69bbSGerhard Engleder failed:
596403f69bbSGerhard Engleder 	disable_taprio(adapter);
597403f69bbSGerhard Engleder 	kfree(qopt);
598403f69bbSGerhard Engleder 
599403f69bbSGerhard Engleder 	return false;
600403f69bbSGerhard Engleder }
601403f69bbSGerhard Engleder 
tsnep_test_taprio_extension(struct tsnep_adapter * adapter)602403f69bbSGerhard Engleder static bool tsnep_test_taprio_extension(struct tsnep_adapter *adapter)
603403f69bbSGerhard Engleder {
604403f69bbSGerhard Engleder 	struct tc_taprio_qopt_offload *qopt;
605403f69bbSGerhard Engleder 	int i;
606403f69bbSGerhard Engleder 
607403f69bbSGerhard Engleder 	qopt = kzalloc(struct_size(qopt, entries, 255), GFP_KERNEL);
608403f69bbSGerhard Engleder 	if (!qopt)
609403f69bbSGerhard Engleder 		return false;
610403f69bbSGerhard Engleder 	for (i = 0; i < 255; i++)
611403f69bbSGerhard Engleder 		qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES;
612403f69bbSGerhard Engleder 
613*2d800bc5SVladimir Oltean 	qopt->cmd = TAPRIO_CMD_REPLACE;
614403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
615403f69bbSGerhard Engleder 	qopt->cycle_time = 100000;
616403f69bbSGerhard Engleder 	qopt->cycle_time_extension = 50000;
617403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x90;
618403f69bbSGerhard Engleder 	qopt->entries[0].interval = 20000;
619403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x91;
620403f69bbSGerhard Engleder 	qopt->entries[1].interval = 80000;
621403f69bbSGerhard Engleder 	qopt->num_entries = 2;
622403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
623403f69bbSGerhard Engleder 		goto failed;
624403f69bbSGerhard Engleder 
625403f69bbSGerhard Engleder 	/* change to different phase */
626403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 50000);
627403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x92;
628403f69bbSGerhard Engleder 	qopt->entries[0].interval = 33000;
629403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x93;
630403f69bbSGerhard Engleder 	qopt->entries[1].interval = 67000;
631403f69bbSGerhard Engleder 	qopt->num_entries = 2;
632403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 2);
633403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
634403f69bbSGerhard Engleder 		goto failed;
635403f69bbSGerhard Engleder 
636403f69bbSGerhard Engleder 	/* change to different phase and longer cycle time */
637403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
638403f69bbSGerhard Engleder 	qopt->cycle_time = 1000000;
639403f69bbSGerhard Engleder 	qopt->cycle_time_extension = 700000;
640403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x94;
641403f69bbSGerhard Engleder 	qopt->entries[0].interval = 400000;
642403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x95;
643403f69bbSGerhard Engleder 	qopt->entries[1].interval = 600000;
644403f69bbSGerhard Engleder 	qopt->num_entries = 2;
645403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 7);
646403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
647403f69bbSGerhard Engleder 		goto failed;
648403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 700000);
649403f69bbSGerhard Engleder 	qopt->cycle_time = 2000000;
650403f69bbSGerhard Engleder 	qopt->cycle_time_extension = 1900000;
651403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x96;
652403f69bbSGerhard Engleder 	qopt->entries[0].interval = 400000;
653403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x97;
654403f69bbSGerhard Engleder 	qopt->entries[1].interval = 1600000;
655403f69bbSGerhard Engleder 	qopt->num_entries = 2;
656403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 9);
657403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
658403f69bbSGerhard Engleder 		goto failed;
659403f69bbSGerhard Engleder 
660403f69bbSGerhard Engleder 	/* change to different phase and shorter cycle time */
661403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
662403f69bbSGerhard Engleder 	qopt->cycle_time = 1500000;
663403f69bbSGerhard Engleder 	qopt->cycle_time_extension = 700000;
664403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x98;
665403f69bbSGerhard Engleder 	qopt->entries[0].interval = 400000;
666403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x99;
667403f69bbSGerhard Engleder 	qopt->entries[1].interval = 600000;
668403f69bbSGerhard Engleder 	qopt->entries[2].gate_mask = 0x9A;
669403f69bbSGerhard Engleder 	qopt->entries[2].interval = 500000;
670403f69bbSGerhard Engleder 	qopt->num_entries = 3;
671403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 3);
672403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
673403f69bbSGerhard Engleder 		goto failed;
674403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 100000);
675403f69bbSGerhard Engleder 	qopt->cycle_time = 500000;
676403f69bbSGerhard Engleder 	qopt->cycle_time_extension = 300000;
677403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0x9B;
678403f69bbSGerhard Engleder 	qopt->entries[0].interval = 150000;
679403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0x9C;
680403f69bbSGerhard Engleder 	qopt->entries[1].interval = 350000;
681403f69bbSGerhard Engleder 	qopt->num_entries = 2;
682403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 9);
683403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
684403f69bbSGerhard Engleder 		goto failed;
685403f69bbSGerhard Engleder 
686403f69bbSGerhard Engleder 	/* change to different cycle time */
687403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
688403f69bbSGerhard Engleder 	qopt->cycle_time = 1000000;
689403f69bbSGerhard Engleder 	qopt->cycle_time_extension = 700000;
690403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0xAD;
691403f69bbSGerhard Engleder 	qopt->entries[0].interval = 400000;
692403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0xAE;
693403f69bbSGerhard Engleder 	qopt->entries[1].interval = 300000;
694403f69bbSGerhard Engleder 	qopt->entries[2].gate_mask = 0xAF;
695403f69bbSGerhard Engleder 	qopt->entries[2].interval = 300000;
696403f69bbSGerhard Engleder 	qopt->num_entries = 3;
697403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
698403f69bbSGerhard Engleder 		goto failed;
699403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
700403f69bbSGerhard Engleder 	qopt->cycle_time = 400000;
701403f69bbSGerhard Engleder 	qopt->cycle_time_extension = 100000;
702403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0xA0;
703403f69bbSGerhard Engleder 	qopt->entries[0].interval = 200000;
704403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0xA1;
705403f69bbSGerhard Engleder 	qopt->entries[1].interval = 200000;
706403f69bbSGerhard Engleder 	qopt->num_entries = 2;
707403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 19);
708403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
709403f69bbSGerhard Engleder 		goto failed;
710403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
711403f69bbSGerhard Engleder 	qopt->cycle_time = 500000;
712403f69bbSGerhard Engleder 	qopt->cycle_time_extension = 499999;
713403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0xB2;
714403f69bbSGerhard Engleder 	qopt->entries[0].interval = 100000;
715403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0xB3;
716403f69bbSGerhard Engleder 	qopt->entries[1].interval = 100000;
717403f69bbSGerhard Engleder 	qopt->entries[2].gate_mask = 0xB4;
718403f69bbSGerhard Engleder 	qopt->entries[2].interval = 100000;
719403f69bbSGerhard Engleder 	qopt->entries[3].gate_mask = 0xB5;
720403f69bbSGerhard Engleder 	qopt->entries[3].interval = 200000;
721403f69bbSGerhard Engleder 	qopt->num_entries = 4;
722403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 19);
723403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
724403f69bbSGerhard Engleder 		goto failed;
725403f69bbSGerhard Engleder 	qopt->base_time = ktime_set(0, 0);
726403f69bbSGerhard Engleder 	qopt->cycle_time = 6000000;
727403f69bbSGerhard Engleder 	qopt->cycle_time_extension = 5999999;
728403f69bbSGerhard Engleder 	qopt->entries[0].gate_mask = 0xC6;
729403f69bbSGerhard Engleder 	qopt->entries[0].interval = 1000000;
730403f69bbSGerhard Engleder 	qopt->entries[1].gate_mask = 0xC7;
731403f69bbSGerhard Engleder 	qopt->entries[1].interval = 1000000;
732403f69bbSGerhard Engleder 	qopt->entries[2].gate_mask = 0xC8;
733403f69bbSGerhard Engleder 	qopt->entries[2].interval = 1000000;
734403f69bbSGerhard Engleder 	qopt->entries[3].gate_mask = 0xC9;
735403f69bbSGerhard Engleder 	qopt->entries[3].interval = 1500000;
736403f69bbSGerhard Engleder 	qopt->entries[4].gate_mask = 0xCA;
737403f69bbSGerhard Engleder 	qopt->entries[4].interval = 1500000;
738403f69bbSGerhard Engleder 	qopt->num_entries = 5;
739403f69bbSGerhard Engleder 	delay_base_time(adapter, qopt, 1);
740403f69bbSGerhard Engleder 	if (!enable_check_taprio(adapter, qopt, 100))
741403f69bbSGerhard Engleder 		goto failed;
742403f69bbSGerhard Engleder 
743403f69bbSGerhard Engleder 	if (!disable_taprio(adapter))
744403f69bbSGerhard Engleder 		goto failed;
745403f69bbSGerhard Engleder 
746403f69bbSGerhard Engleder 	kfree(qopt);
747403f69bbSGerhard Engleder 
748403f69bbSGerhard Engleder 	return true;
749403f69bbSGerhard Engleder 
750403f69bbSGerhard Engleder failed:
751403f69bbSGerhard Engleder 	disable_taprio(adapter);
752403f69bbSGerhard Engleder 	kfree(qopt);
753403f69bbSGerhard Engleder 
754403f69bbSGerhard Engleder 	return false;
755403f69bbSGerhard Engleder }
756403f69bbSGerhard Engleder 
tsnep_ethtool_get_test_count(void)757403f69bbSGerhard Engleder int tsnep_ethtool_get_test_count(void)
758403f69bbSGerhard Engleder {
759403f69bbSGerhard Engleder 	return TSNEP_TEST_COUNT;
760403f69bbSGerhard Engleder }
761403f69bbSGerhard Engleder 
tsnep_ethtool_get_test_strings(u8 * data)762403f69bbSGerhard Engleder void tsnep_ethtool_get_test_strings(u8 *data)
763403f69bbSGerhard Engleder {
764403f69bbSGerhard Engleder 	memcpy(data, tsnep_test_strings, sizeof(tsnep_test_strings));
765403f69bbSGerhard Engleder }
766403f69bbSGerhard Engleder 
tsnep_ethtool_self_test(struct net_device * netdev,struct ethtool_test * eth_test,u64 * data)767403f69bbSGerhard Engleder void tsnep_ethtool_self_test(struct net_device *netdev,
768403f69bbSGerhard Engleder 			     struct ethtool_test *eth_test, u64 *data)
769403f69bbSGerhard Engleder {
770403f69bbSGerhard Engleder 	struct tsnep_adapter *adapter = netdev_priv(netdev);
771403f69bbSGerhard Engleder 
772403f69bbSGerhard Engleder 	eth_test->len = TSNEP_TEST_COUNT;
773403f69bbSGerhard Engleder 
774403f69bbSGerhard Engleder 	if (eth_test->flags != ETH_TEST_FL_OFFLINE) {
775403f69bbSGerhard Engleder 		/* no tests are done online */
776403f69bbSGerhard Engleder 		data[TSNEP_TEST_ENABLE] = 0;
777403f69bbSGerhard Engleder 		data[TSNEP_TEST_TAPRIO] = 0;
778403f69bbSGerhard Engleder 		data[TSNEP_TEST_TAPRIO_CHANGE] = 0;
779403f69bbSGerhard Engleder 		data[TSNEP_TEST_TAPRIO_EXTENSION] = 0;
780403f69bbSGerhard Engleder 
781403f69bbSGerhard Engleder 		return;
782403f69bbSGerhard Engleder 	}
783403f69bbSGerhard Engleder 
784403f69bbSGerhard Engleder 	if (tsnep_test_gc_enable(adapter)) {
785403f69bbSGerhard Engleder 		data[TSNEP_TEST_ENABLE] = 0;
786403f69bbSGerhard Engleder 	} else {
787403f69bbSGerhard Engleder 		eth_test->flags |= ETH_TEST_FL_FAILED;
788403f69bbSGerhard Engleder 		data[TSNEP_TEST_ENABLE] = 1;
789403f69bbSGerhard Engleder 	}
790403f69bbSGerhard Engleder 
791403f69bbSGerhard Engleder 	if (tsnep_test_taprio(adapter)) {
792403f69bbSGerhard Engleder 		data[TSNEP_TEST_TAPRIO] = 0;
793403f69bbSGerhard Engleder 	} else {
794403f69bbSGerhard Engleder 		eth_test->flags |= ETH_TEST_FL_FAILED;
795403f69bbSGerhard Engleder 		data[TSNEP_TEST_TAPRIO] = 1;
796403f69bbSGerhard Engleder 	}
797403f69bbSGerhard Engleder 
798403f69bbSGerhard Engleder 	if (tsnep_test_taprio_change(adapter)) {
799403f69bbSGerhard Engleder 		data[TSNEP_TEST_TAPRIO_CHANGE] = 0;
800403f69bbSGerhard Engleder 	} else {
801403f69bbSGerhard Engleder 		eth_test->flags |= ETH_TEST_FL_FAILED;
802403f69bbSGerhard Engleder 		data[TSNEP_TEST_TAPRIO_CHANGE] = 1;
803403f69bbSGerhard Engleder 	}
804403f69bbSGerhard Engleder 
805403f69bbSGerhard Engleder 	if (tsnep_test_taprio_extension(adapter)) {
806403f69bbSGerhard Engleder 		data[TSNEP_TEST_TAPRIO_EXTENSION] = 0;
807403f69bbSGerhard Engleder 	} else {
808403f69bbSGerhard Engleder 		eth_test->flags |= ETH_TEST_FL_FAILED;
809403f69bbSGerhard Engleder 		data[TSNEP_TEST_TAPRIO_EXTENSION] = 1;
810403f69bbSGerhard Engleder 	}
811403f69bbSGerhard Engleder }
812