162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright (C) 2021 Gerhard Engleder <gerhard@engleder-embedded.com> */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include "tsnep.h"
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <net/pkt_sched.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_cienum tsnep_test {
962306a36Sopenharmony_ci	TSNEP_TEST_ENABLE = 0,
1062306a36Sopenharmony_ci	TSNEP_TEST_TAPRIO,
1162306a36Sopenharmony_ci	TSNEP_TEST_TAPRIO_CHANGE,
1262306a36Sopenharmony_ci	TSNEP_TEST_TAPRIO_EXTENSION,
1362306a36Sopenharmony_ci};
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_cistatic const char tsnep_test_strings[][ETH_GSTRING_LEN] = {
1662306a36Sopenharmony_ci	"Enable timeout        (offline)",
1762306a36Sopenharmony_ci	"TAPRIO                (offline)",
1862306a36Sopenharmony_ci	"TAPRIO change         (offline)",
1962306a36Sopenharmony_ci	"TAPRIO extension      (offline)",
2062306a36Sopenharmony_ci};
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define TSNEP_TEST_COUNT (sizeof(tsnep_test_strings) / ETH_GSTRING_LEN)
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_cistatic bool enable_gc_timeout(struct tsnep_adapter *adapter)
2562306a36Sopenharmony_ci{
2662306a36Sopenharmony_ci	iowrite8(TSNEP_GC_ENABLE_TIMEOUT, adapter->addr + TSNEP_GC);
2762306a36Sopenharmony_ci	if (!(ioread32(adapter->addr + TSNEP_GC) & TSNEP_GC_TIMEOUT_ACTIVE))
2862306a36Sopenharmony_ci		return false;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	return true;
3162306a36Sopenharmony_ci}
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_cistatic bool gc_timeout_signaled(struct tsnep_adapter *adapter)
3462306a36Sopenharmony_ci{
3562306a36Sopenharmony_ci	if (ioread32(adapter->addr + TSNEP_GC) & TSNEP_GC_TIMEOUT_SIGNAL)
3662306a36Sopenharmony_ci		return true;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	return false;
3962306a36Sopenharmony_ci}
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistatic bool ack_gc_timeout(struct tsnep_adapter *adapter)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci	iowrite8(TSNEP_GC_ENABLE_TIMEOUT, adapter->addr + TSNEP_GC);
4462306a36Sopenharmony_ci	if (ioread32(adapter->addr + TSNEP_GC) &
4562306a36Sopenharmony_ci	    (TSNEP_GC_TIMEOUT_ACTIVE | TSNEP_GC_TIMEOUT_SIGNAL))
4662306a36Sopenharmony_ci		return false;
4762306a36Sopenharmony_ci	return true;
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic bool enable_gc(struct tsnep_adapter *adapter, bool a)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	u8 enable;
5362306a36Sopenharmony_ci	u8 active;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	if (a) {
5662306a36Sopenharmony_ci		enable = TSNEP_GC_ENABLE_A;
5762306a36Sopenharmony_ci		active = TSNEP_GC_ACTIVE_A;
5862306a36Sopenharmony_ci	} else {
5962306a36Sopenharmony_ci		enable = TSNEP_GC_ENABLE_B;
6062306a36Sopenharmony_ci		active = TSNEP_GC_ACTIVE_B;
6162306a36Sopenharmony_ci	}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	iowrite8(enable, adapter->addr + TSNEP_GC);
6462306a36Sopenharmony_ci	if (!(ioread32(adapter->addr + TSNEP_GC) & active))
6562306a36Sopenharmony_ci		return false;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	return true;
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistatic bool disable_gc(struct tsnep_adapter *adapter)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	iowrite8(TSNEP_GC_DISABLE, adapter->addr + TSNEP_GC);
7362306a36Sopenharmony_ci	if (ioread32(adapter->addr + TSNEP_GC) &
7462306a36Sopenharmony_ci	    (TSNEP_GC_ACTIVE_A | TSNEP_GC_ACTIVE_B))
7562306a36Sopenharmony_ci		return false;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	return true;
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistatic bool gc_delayed_enable(struct tsnep_adapter *adapter, bool a, int delay)
8162306a36Sopenharmony_ci{
8262306a36Sopenharmony_ci	u64 before, after;
8362306a36Sopenharmony_ci	u32 time;
8462306a36Sopenharmony_ci	bool enabled;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	if (!disable_gc(adapter))
8762306a36Sopenharmony_ci		return false;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	before = ktime_get_ns();
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	if (!enable_gc_timeout(adapter))
9262306a36Sopenharmony_ci		return false;
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	/* for start time after timeout, the timeout can guarantee, that enable
9562306a36Sopenharmony_ci	 * is blocked if too late
9662306a36Sopenharmony_ci	 */
9762306a36Sopenharmony_ci	time = ioread32(adapter->addr + ECM_SYSTEM_TIME_LOW);
9862306a36Sopenharmony_ci	time += TSNEP_GC_TIMEOUT;
9962306a36Sopenharmony_ci	iowrite32(time, adapter->addr + TSNEP_GC_TIME);
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	ndelay(delay);
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	enabled = enable_gc(adapter, a);
10462306a36Sopenharmony_ci	after = ktime_get_ns();
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	if (delay > TSNEP_GC_TIMEOUT) {
10762306a36Sopenharmony_ci		/* timeout must have blocked enable */
10862306a36Sopenharmony_ci		if (enabled)
10962306a36Sopenharmony_ci			return false;
11062306a36Sopenharmony_ci	} else if ((after - before) < TSNEP_GC_TIMEOUT * 14 / 16) {
11162306a36Sopenharmony_ci		/* timeout must not have blocked enable */
11262306a36Sopenharmony_ci		if (!enabled)
11362306a36Sopenharmony_ci			return false;
11462306a36Sopenharmony_ci	}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	if (enabled) {
11762306a36Sopenharmony_ci		if (gc_timeout_signaled(adapter))
11862306a36Sopenharmony_ci			return false;
11962306a36Sopenharmony_ci	} else {
12062306a36Sopenharmony_ci		if (!gc_timeout_signaled(adapter))
12162306a36Sopenharmony_ci			return false;
12262306a36Sopenharmony_ci		if (!ack_gc_timeout(adapter))
12362306a36Sopenharmony_ci			return false;
12462306a36Sopenharmony_ci	}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	if (!disable_gc(adapter))
12762306a36Sopenharmony_ci		return false;
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	return true;
13062306a36Sopenharmony_ci}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cistatic bool tsnep_test_gc_enable(struct tsnep_adapter *adapter)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	int i;
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	iowrite32(0x80000001, adapter->addr + TSNEP_GCL_A + 0);
13762306a36Sopenharmony_ci	iowrite32(100000, adapter->addr + TSNEP_GCL_A + 4);
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	for (i = 0; i < 200000; i += 100) {
14062306a36Sopenharmony_ci		if (!gc_delayed_enable(adapter, true, i))
14162306a36Sopenharmony_ci			return false;
14262306a36Sopenharmony_ci	}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	iowrite32(0x80000001, adapter->addr + TSNEP_GCL_B + 0);
14562306a36Sopenharmony_ci	iowrite32(100000, adapter->addr + TSNEP_GCL_B + 4);
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	for (i = 0; i < 200000; i += 100) {
14862306a36Sopenharmony_ci		if (!gc_delayed_enable(adapter, false, i))
14962306a36Sopenharmony_ci			return false;
15062306a36Sopenharmony_ci	}
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	return true;
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_cistatic void delay_base_time(struct tsnep_adapter *adapter,
15662306a36Sopenharmony_ci			    struct tc_taprio_qopt_offload *qopt, s64 ms)
15762306a36Sopenharmony_ci{
15862306a36Sopenharmony_ci	u64 system_time;
15962306a36Sopenharmony_ci	u64 base_time = ktime_to_ns(qopt->base_time);
16062306a36Sopenharmony_ci	u64 n;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	tsnep_get_system_time(adapter, &system_time);
16362306a36Sopenharmony_ci	system_time += ms * 1000000;
16462306a36Sopenharmony_ci	n = div64_u64(system_time - base_time, qopt->cycle_time);
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	qopt->base_time = ktime_add_ns(qopt->base_time,
16762306a36Sopenharmony_ci				       (n + 1) * qopt->cycle_time);
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic void get_gate_state(struct tsnep_adapter *adapter, u32 *gc, u32 *gc_time,
17162306a36Sopenharmony_ci			   u64 *system_time)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	u32 time_high_before;
17462306a36Sopenharmony_ci	u32 time_low;
17562306a36Sopenharmony_ci	u32 time_high;
17662306a36Sopenharmony_ci	u32 gc_time_before;
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	time_high = ioread32(adapter->addr + ECM_SYSTEM_TIME_HIGH);
17962306a36Sopenharmony_ci	*gc_time = ioread32(adapter->addr + TSNEP_GC_TIME);
18062306a36Sopenharmony_ci	do {
18162306a36Sopenharmony_ci		time_low = ioread32(adapter->addr + ECM_SYSTEM_TIME_LOW);
18262306a36Sopenharmony_ci		*gc = ioread32(adapter->addr + TSNEP_GC);
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci		gc_time_before = *gc_time;
18562306a36Sopenharmony_ci		*gc_time = ioread32(adapter->addr + TSNEP_GC_TIME);
18662306a36Sopenharmony_ci		time_high_before = time_high;
18762306a36Sopenharmony_ci		time_high = ioread32(adapter->addr + ECM_SYSTEM_TIME_HIGH);
18862306a36Sopenharmony_ci	} while ((time_high != time_high_before) ||
18962306a36Sopenharmony_ci		 (*gc_time != gc_time_before));
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	*system_time = (((u64)time_high) << 32) | ((u64)time_low);
19262306a36Sopenharmony_ci}
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_cistatic int get_operation(struct tsnep_gcl *gcl, u64 system_time, u64 *next)
19562306a36Sopenharmony_ci{
19662306a36Sopenharmony_ci	u64 n = div64_u64(system_time - gcl->base_time, gcl->cycle_time);
19762306a36Sopenharmony_ci	u64 cycle_start = gcl->base_time + gcl->cycle_time * n;
19862306a36Sopenharmony_ci	int i;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	*next = cycle_start;
20162306a36Sopenharmony_ci	for (i = 0; i < gcl->count; i++) {
20262306a36Sopenharmony_ci		*next += gcl->operation[i].interval;
20362306a36Sopenharmony_ci		if (*next > system_time)
20462306a36Sopenharmony_ci			break;
20562306a36Sopenharmony_ci	}
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	return i;
20862306a36Sopenharmony_ci}
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_cistatic bool check_gate(struct tsnep_adapter *adapter)
21162306a36Sopenharmony_ci{
21262306a36Sopenharmony_ci	u32 gc_time;
21362306a36Sopenharmony_ci	u32 gc;
21462306a36Sopenharmony_ci	u64 system_time;
21562306a36Sopenharmony_ci	struct tsnep_gcl *curr;
21662306a36Sopenharmony_ci	struct tsnep_gcl *prev;
21762306a36Sopenharmony_ci	u64 next_time;
21862306a36Sopenharmony_ci	u8 gate_open;
21962306a36Sopenharmony_ci	u8 next_gate_open;
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	get_gate_state(adapter, &gc, &gc_time, &system_time);
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	if (gc & TSNEP_GC_ACTIVE_A) {
22462306a36Sopenharmony_ci		curr = &adapter->gcl[0];
22562306a36Sopenharmony_ci		prev = &adapter->gcl[1];
22662306a36Sopenharmony_ci	} else if (gc & TSNEP_GC_ACTIVE_B) {
22762306a36Sopenharmony_ci		curr = &adapter->gcl[1];
22862306a36Sopenharmony_ci		prev = &adapter->gcl[0];
22962306a36Sopenharmony_ci	} else {
23062306a36Sopenharmony_ci		return false;
23162306a36Sopenharmony_ci	}
23262306a36Sopenharmony_ci	if (curr->start_time <= system_time) {
23362306a36Sopenharmony_ci		/* GCL is already active */
23462306a36Sopenharmony_ci		int index;
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci		index = get_operation(curr, system_time, &next_time);
23762306a36Sopenharmony_ci		gate_open = curr->operation[index].properties & TSNEP_GCL_MASK;
23862306a36Sopenharmony_ci		if (index == curr->count - 1)
23962306a36Sopenharmony_ci			index = 0;
24062306a36Sopenharmony_ci		else
24162306a36Sopenharmony_ci			index++;
24262306a36Sopenharmony_ci		next_gate_open =
24362306a36Sopenharmony_ci			curr->operation[index].properties & TSNEP_GCL_MASK;
24462306a36Sopenharmony_ci	} else if (curr->change) {
24562306a36Sopenharmony_ci		/* operation of previous GCL is active */
24662306a36Sopenharmony_ci		int index;
24762306a36Sopenharmony_ci		u64 start_before;
24862306a36Sopenharmony_ci		u64 n;
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci		index = get_operation(prev, system_time, &next_time);
25162306a36Sopenharmony_ci		next_time = curr->start_time;
25262306a36Sopenharmony_ci		start_before = prev->base_time;
25362306a36Sopenharmony_ci		n = div64_u64(curr->start_time - start_before,
25462306a36Sopenharmony_ci			      prev->cycle_time);
25562306a36Sopenharmony_ci		start_before += n * prev->cycle_time;
25662306a36Sopenharmony_ci		if (curr->start_time == start_before)
25762306a36Sopenharmony_ci			start_before -= prev->cycle_time;
25862306a36Sopenharmony_ci		if (((start_before + prev->cycle_time_extension) >=
25962306a36Sopenharmony_ci		     curr->start_time) &&
26062306a36Sopenharmony_ci		    (curr->start_time - prev->cycle_time_extension <=
26162306a36Sopenharmony_ci		     system_time)) {
26262306a36Sopenharmony_ci			/* extend */
26362306a36Sopenharmony_ci			index = prev->count - 1;
26462306a36Sopenharmony_ci		}
26562306a36Sopenharmony_ci		gate_open = prev->operation[index].properties & TSNEP_GCL_MASK;
26662306a36Sopenharmony_ci		next_gate_open =
26762306a36Sopenharmony_ci			curr->operation[0].properties & TSNEP_GCL_MASK;
26862306a36Sopenharmony_ci	} else {
26962306a36Sopenharmony_ci		/* GCL is waiting for start */
27062306a36Sopenharmony_ci		next_time = curr->start_time;
27162306a36Sopenharmony_ci		gate_open = 0xFF;
27262306a36Sopenharmony_ci		next_gate_open = curr->operation[0].properties & TSNEP_GCL_MASK;
27362306a36Sopenharmony_ci	}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	if (gc_time != (next_time & 0xFFFFFFFF)) {
27662306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev, "gate control time 0x%x!=0x%llx\n",
27762306a36Sopenharmony_ci			gc_time, next_time);
27862306a36Sopenharmony_ci		return false;
27962306a36Sopenharmony_ci	}
28062306a36Sopenharmony_ci	if (((gc & TSNEP_GC_OPEN) >> TSNEP_GC_OPEN_SHIFT) != gate_open) {
28162306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev,
28262306a36Sopenharmony_ci			"gate control open 0x%02x!=0x%02x\n",
28362306a36Sopenharmony_ci			((gc & TSNEP_GC_OPEN) >> TSNEP_GC_OPEN_SHIFT),
28462306a36Sopenharmony_ci			gate_open);
28562306a36Sopenharmony_ci		return false;
28662306a36Sopenharmony_ci	}
28762306a36Sopenharmony_ci	if (((gc & TSNEP_GC_NEXT_OPEN) >> TSNEP_GC_NEXT_OPEN_SHIFT) !=
28862306a36Sopenharmony_ci	    next_gate_open) {
28962306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev,
29062306a36Sopenharmony_ci			"gate control next open 0x%02x!=0x%02x\n",
29162306a36Sopenharmony_ci			((gc & TSNEP_GC_NEXT_OPEN) >> TSNEP_GC_NEXT_OPEN_SHIFT),
29262306a36Sopenharmony_ci			next_gate_open);
29362306a36Sopenharmony_ci		return false;
29462306a36Sopenharmony_ci	}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	return true;
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_cistatic bool check_gate_duration(struct tsnep_adapter *adapter, s64 ms)
30062306a36Sopenharmony_ci{
30162306a36Sopenharmony_ci	ktime_t start = ktime_get();
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	do {
30462306a36Sopenharmony_ci		if (!check_gate(adapter))
30562306a36Sopenharmony_ci			return false;
30662306a36Sopenharmony_ci	} while (ktime_ms_delta(ktime_get(), start) < ms);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	return true;
30962306a36Sopenharmony_ci}
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_cistatic bool enable_check_taprio(struct tsnep_adapter *adapter,
31262306a36Sopenharmony_ci				struct tc_taprio_qopt_offload *qopt, s64 ms)
31362306a36Sopenharmony_ci{
31462306a36Sopenharmony_ci	int retval;
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	retval = tsnep_tc_setup(adapter->netdev, TC_SETUP_QDISC_TAPRIO, qopt);
31762306a36Sopenharmony_ci	if (retval)
31862306a36Sopenharmony_ci		return false;
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	if (!check_gate_duration(adapter, ms))
32162306a36Sopenharmony_ci		return false;
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	return true;
32462306a36Sopenharmony_ci}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_cistatic bool disable_taprio(struct tsnep_adapter *adapter)
32762306a36Sopenharmony_ci{
32862306a36Sopenharmony_ci	struct tc_taprio_qopt_offload qopt;
32962306a36Sopenharmony_ci	int retval;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	memset(&qopt, 0, sizeof(qopt));
33262306a36Sopenharmony_ci	qopt.cmd = TAPRIO_CMD_DESTROY;
33362306a36Sopenharmony_ci	retval = tsnep_tc_setup(adapter->netdev, TC_SETUP_QDISC_TAPRIO, &qopt);
33462306a36Sopenharmony_ci	if (retval)
33562306a36Sopenharmony_ci		return false;
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	return true;
33862306a36Sopenharmony_ci}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_cistatic bool run_taprio(struct tsnep_adapter *adapter,
34162306a36Sopenharmony_ci		       struct tc_taprio_qopt_offload *qopt, s64 ms)
34262306a36Sopenharmony_ci{
34362306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, ms))
34462306a36Sopenharmony_ci		return false;
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	if (!disable_taprio(adapter))
34762306a36Sopenharmony_ci		return false;
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	return true;
35062306a36Sopenharmony_ci}
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_cistatic bool tsnep_test_taprio(struct tsnep_adapter *adapter)
35362306a36Sopenharmony_ci{
35462306a36Sopenharmony_ci	struct tc_taprio_qopt_offload *qopt;
35562306a36Sopenharmony_ci	int i;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	qopt = kzalloc(struct_size(qopt, entries, 255), GFP_KERNEL);
35862306a36Sopenharmony_ci	if (!qopt)
35962306a36Sopenharmony_ci		return false;
36062306a36Sopenharmony_ci	for (i = 0; i < 255; i++)
36162306a36Sopenharmony_ci		qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES;
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	qopt->cmd = TAPRIO_CMD_REPLACE;
36462306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
36562306a36Sopenharmony_ci	qopt->cycle_time = 1500000;
36662306a36Sopenharmony_ci	qopt->cycle_time_extension = 0;
36762306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x02;
36862306a36Sopenharmony_ci	qopt->entries[0].interval = 200000;
36962306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x03;
37062306a36Sopenharmony_ci	qopt->entries[1].interval = 800000;
37162306a36Sopenharmony_ci	qopt->entries[2].gate_mask = 0x07;
37262306a36Sopenharmony_ci	qopt->entries[2].interval = 240000;
37362306a36Sopenharmony_ci	qopt->entries[3].gate_mask = 0x01;
37462306a36Sopenharmony_ci	qopt->entries[3].interval = 80000;
37562306a36Sopenharmony_ci	qopt->entries[4].gate_mask = 0x04;
37662306a36Sopenharmony_ci	qopt->entries[4].interval = 70000;
37762306a36Sopenharmony_ci	qopt->entries[5].gate_mask = 0x06;
37862306a36Sopenharmony_ci	qopt->entries[5].interval = 60000;
37962306a36Sopenharmony_ci	qopt->entries[6].gate_mask = 0x0F;
38062306a36Sopenharmony_ci	qopt->entries[6].interval = 50000;
38162306a36Sopenharmony_ci	qopt->num_entries = 7;
38262306a36Sopenharmony_ci	if (!run_taprio(adapter, qopt, 100))
38362306a36Sopenharmony_ci		goto failed;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	qopt->cmd = TAPRIO_CMD_REPLACE;
38662306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
38762306a36Sopenharmony_ci	qopt->cycle_time = 411854;
38862306a36Sopenharmony_ci	qopt->cycle_time_extension = 0;
38962306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x17;
39062306a36Sopenharmony_ci	qopt->entries[0].interval = 23842;
39162306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x16;
39262306a36Sopenharmony_ci	qopt->entries[1].interval = 13482;
39362306a36Sopenharmony_ci	qopt->entries[2].gate_mask = 0x15;
39462306a36Sopenharmony_ci	qopt->entries[2].interval = 49428;
39562306a36Sopenharmony_ci	qopt->entries[3].gate_mask = 0x14;
39662306a36Sopenharmony_ci	qopt->entries[3].interval = 38189;
39762306a36Sopenharmony_ci	qopt->entries[4].gate_mask = 0x13;
39862306a36Sopenharmony_ci	qopt->entries[4].interval = 92321;
39962306a36Sopenharmony_ci	qopt->entries[5].gate_mask = 0x12;
40062306a36Sopenharmony_ci	qopt->entries[5].interval = 71239;
40162306a36Sopenharmony_ci	qopt->entries[6].gate_mask = 0x11;
40262306a36Sopenharmony_ci	qopt->entries[6].interval = 69932;
40362306a36Sopenharmony_ci	qopt->entries[7].gate_mask = 0x10;
40462306a36Sopenharmony_ci	qopt->entries[7].interval = 53421;
40562306a36Sopenharmony_ci	qopt->num_entries = 8;
40662306a36Sopenharmony_ci	if (!run_taprio(adapter, qopt, 100))
40762306a36Sopenharmony_ci		goto failed;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	qopt->cmd = TAPRIO_CMD_REPLACE;
41062306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
41162306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 12);
41262306a36Sopenharmony_ci	qopt->cycle_time = 125000;
41362306a36Sopenharmony_ci	qopt->cycle_time_extension = 0;
41462306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x27;
41562306a36Sopenharmony_ci	qopt->entries[0].interval = 15000;
41662306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x26;
41762306a36Sopenharmony_ci	qopt->entries[1].interval = 15000;
41862306a36Sopenharmony_ci	qopt->entries[2].gate_mask = 0x25;
41962306a36Sopenharmony_ci	qopt->entries[2].interval = 12500;
42062306a36Sopenharmony_ci	qopt->entries[3].gate_mask = 0x24;
42162306a36Sopenharmony_ci	qopt->entries[3].interval = 17500;
42262306a36Sopenharmony_ci	qopt->entries[4].gate_mask = 0x23;
42362306a36Sopenharmony_ci	qopt->entries[4].interval = 10000;
42462306a36Sopenharmony_ci	qopt->entries[5].gate_mask = 0x22;
42562306a36Sopenharmony_ci	qopt->entries[5].interval = 11000;
42662306a36Sopenharmony_ci	qopt->entries[6].gate_mask = 0x21;
42762306a36Sopenharmony_ci	qopt->entries[6].interval = 9000;
42862306a36Sopenharmony_ci	qopt->entries[7].gate_mask = 0x20;
42962306a36Sopenharmony_ci	qopt->entries[7].interval = 10000;
43062306a36Sopenharmony_ci	qopt->entries[8].gate_mask = 0x20;
43162306a36Sopenharmony_ci	qopt->entries[8].interval = 12500;
43262306a36Sopenharmony_ci	qopt->entries[9].gate_mask = 0x20;
43362306a36Sopenharmony_ci	qopt->entries[9].interval = 12500;
43462306a36Sopenharmony_ci	qopt->num_entries = 10;
43562306a36Sopenharmony_ci	if (!run_taprio(adapter, qopt, 100))
43662306a36Sopenharmony_ci		goto failed;
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	kfree(qopt);
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci	return true;
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_cifailed:
44362306a36Sopenharmony_ci	disable_taprio(adapter);
44462306a36Sopenharmony_ci	kfree(qopt);
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci	return false;
44762306a36Sopenharmony_ci}
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_cistatic bool tsnep_test_taprio_change(struct tsnep_adapter *adapter)
45062306a36Sopenharmony_ci{
45162306a36Sopenharmony_ci	struct tc_taprio_qopt_offload *qopt;
45262306a36Sopenharmony_ci	int i;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	qopt = kzalloc(struct_size(qopt, entries, 255), GFP_KERNEL);
45562306a36Sopenharmony_ci	if (!qopt)
45662306a36Sopenharmony_ci		return false;
45762306a36Sopenharmony_ci	for (i = 0; i < 255; i++)
45862306a36Sopenharmony_ci		qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES;
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	qopt->cmd = TAPRIO_CMD_REPLACE;
46162306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
46262306a36Sopenharmony_ci	qopt->cycle_time = 100000;
46362306a36Sopenharmony_ci	qopt->cycle_time_extension = 0;
46462306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x30;
46562306a36Sopenharmony_ci	qopt->entries[0].interval = 20000;
46662306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x31;
46762306a36Sopenharmony_ci	qopt->entries[1].interval = 80000;
46862306a36Sopenharmony_ci	qopt->num_entries = 2;
46962306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
47062306a36Sopenharmony_ci		goto failed;
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	/* change to identical */
47362306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
47462306a36Sopenharmony_ci		goto failed;
47562306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 17);
47662306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
47762306a36Sopenharmony_ci		goto failed;
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	/* change to same cycle time */
48062306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
48162306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x42;
48262306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x43;
48362306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 2);
48462306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
48562306a36Sopenharmony_ci		goto failed;
48662306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
48762306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x54;
48862306a36Sopenharmony_ci	qopt->entries[0].interval = 33333;
48962306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x55;
49062306a36Sopenharmony_ci	qopt->entries[1].interval = 66667;
49162306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 23);
49262306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
49362306a36Sopenharmony_ci		goto failed;
49462306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
49562306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x66;
49662306a36Sopenharmony_ci	qopt->entries[0].interval = 50000;
49762306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x67;
49862306a36Sopenharmony_ci	qopt->entries[1].interval = 25000;
49962306a36Sopenharmony_ci	qopt->entries[2].gate_mask = 0x68;
50062306a36Sopenharmony_ci	qopt->entries[2].interval = 25000;
50162306a36Sopenharmony_ci	qopt->num_entries = 3;
50262306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 11);
50362306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
50462306a36Sopenharmony_ci		goto failed;
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci	/* change to multiple of cycle time */
50762306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
50862306a36Sopenharmony_ci	qopt->cycle_time = 200000;
50962306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x79;
51062306a36Sopenharmony_ci	qopt->entries[0].interval = 50000;
51162306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x7A;
51262306a36Sopenharmony_ci	qopt->entries[1].interval = 150000;
51362306a36Sopenharmony_ci	qopt->num_entries = 2;
51462306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 11);
51562306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
51662306a36Sopenharmony_ci		goto failed;
51762306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
51862306a36Sopenharmony_ci	qopt->cycle_time = 1000000;
51962306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x7B;
52062306a36Sopenharmony_ci	qopt->entries[0].interval = 125000;
52162306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x7C;
52262306a36Sopenharmony_ci	qopt->entries[1].interval = 250000;
52362306a36Sopenharmony_ci	qopt->entries[2].gate_mask = 0x7D;
52462306a36Sopenharmony_ci	qopt->entries[2].interval = 375000;
52562306a36Sopenharmony_ci	qopt->entries[3].gate_mask = 0x7E;
52662306a36Sopenharmony_ci	qopt->entries[3].interval = 250000;
52762306a36Sopenharmony_ci	qopt->num_entries = 4;
52862306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 3);
52962306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
53062306a36Sopenharmony_ci		goto failed;
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	/* change to shorter cycle time */
53362306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
53462306a36Sopenharmony_ci	qopt->cycle_time = 333333;
53562306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x8F;
53662306a36Sopenharmony_ci	qopt->entries[0].interval = 166666;
53762306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x80;
53862306a36Sopenharmony_ci	qopt->entries[1].interval = 166667;
53962306a36Sopenharmony_ci	qopt->num_entries = 2;
54062306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 11);
54162306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
54262306a36Sopenharmony_ci		goto failed;
54362306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
54462306a36Sopenharmony_ci	qopt->cycle_time = 62500;
54562306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x81;
54662306a36Sopenharmony_ci	qopt->entries[0].interval = 31250;
54762306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x82;
54862306a36Sopenharmony_ci	qopt->entries[1].interval = 15625;
54962306a36Sopenharmony_ci	qopt->entries[2].gate_mask = 0x83;
55062306a36Sopenharmony_ci	qopt->entries[2].interval = 15625;
55162306a36Sopenharmony_ci	qopt->num_entries = 3;
55262306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 1);
55362306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
55462306a36Sopenharmony_ci		goto failed;
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	/* change to longer cycle time */
55762306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
55862306a36Sopenharmony_ci	qopt->cycle_time = 400000;
55962306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x84;
56062306a36Sopenharmony_ci	qopt->entries[0].interval = 100000;
56162306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x85;
56262306a36Sopenharmony_ci	qopt->entries[1].interval = 100000;
56362306a36Sopenharmony_ci	qopt->entries[2].gate_mask = 0x86;
56462306a36Sopenharmony_ci	qopt->entries[2].interval = 100000;
56562306a36Sopenharmony_ci	qopt->entries[3].gate_mask = 0x87;
56662306a36Sopenharmony_ci	qopt->entries[3].interval = 100000;
56762306a36Sopenharmony_ci	qopt->num_entries = 4;
56862306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 7);
56962306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
57062306a36Sopenharmony_ci		goto failed;
57162306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
57262306a36Sopenharmony_ci	qopt->cycle_time = 1700000;
57362306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x88;
57462306a36Sopenharmony_ci	qopt->entries[0].interval = 200000;
57562306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x89;
57662306a36Sopenharmony_ci	qopt->entries[1].interval = 300000;
57762306a36Sopenharmony_ci	qopt->entries[2].gate_mask = 0x8A;
57862306a36Sopenharmony_ci	qopt->entries[2].interval = 600000;
57962306a36Sopenharmony_ci	qopt->entries[3].gate_mask = 0x8B;
58062306a36Sopenharmony_ci	qopt->entries[3].interval = 100000;
58162306a36Sopenharmony_ci	qopt->entries[4].gate_mask = 0x8C;
58262306a36Sopenharmony_ci	qopt->entries[4].interval = 500000;
58362306a36Sopenharmony_ci	qopt->num_entries = 5;
58462306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 6);
58562306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
58662306a36Sopenharmony_ci		goto failed;
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci	if (!disable_taprio(adapter))
58962306a36Sopenharmony_ci		goto failed;
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	kfree(qopt);
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci	return true;
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_cifailed:
59662306a36Sopenharmony_ci	disable_taprio(adapter);
59762306a36Sopenharmony_ci	kfree(qopt);
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	return false;
60062306a36Sopenharmony_ci}
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_cistatic bool tsnep_test_taprio_extension(struct tsnep_adapter *adapter)
60362306a36Sopenharmony_ci{
60462306a36Sopenharmony_ci	struct tc_taprio_qopt_offload *qopt;
60562306a36Sopenharmony_ci	int i;
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	qopt = kzalloc(struct_size(qopt, entries, 255), GFP_KERNEL);
60862306a36Sopenharmony_ci	if (!qopt)
60962306a36Sopenharmony_ci		return false;
61062306a36Sopenharmony_ci	for (i = 0; i < 255; i++)
61162306a36Sopenharmony_ci		qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES;
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	qopt->cmd = TAPRIO_CMD_REPLACE;
61462306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
61562306a36Sopenharmony_ci	qopt->cycle_time = 100000;
61662306a36Sopenharmony_ci	qopt->cycle_time_extension = 50000;
61762306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x90;
61862306a36Sopenharmony_ci	qopt->entries[0].interval = 20000;
61962306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x91;
62062306a36Sopenharmony_ci	qopt->entries[1].interval = 80000;
62162306a36Sopenharmony_ci	qopt->num_entries = 2;
62262306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
62362306a36Sopenharmony_ci		goto failed;
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci	/* change to different phase */
62662306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 50000);
62762306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x92;
62862306a36Sopenharmony_ci	qopt->entries[0].interval = 33000;
62962306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x93;
63062306a36Sopenharmony_ci	qopt->entries[1].interval = 67000;
63162306a36Sopenharmony_ci	qopt->num_entries = 2;
63262306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 2);
63362306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
63462306a36Sopenharmony_ci		goto failed;
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	/* change to different phase and longer cycle time */
63762306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
63862306a36Sopenharmony_ci	qopt->cycle_time = 1000000;
63962306a36Sopenharmony_ci	qopt->cycle_time_extension = 700000;
64062306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x94;
64162306a36Sopenharmony_ci	qopt->entries[0].interval = 400000;
64262306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x95;
64362306a36Sopenharmony_ci	qopt->entries[1].interval = 600000;
64462306a36Sopenharmony_ci	qopt->num_entries = 2;
64562306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 7);
64662306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
64762306a36Sopenharmony_ci		goto failed;
64862306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 700000);
64962306a36Sopenharmony_ci	qopt->cycle_time = 2000000;
65062306a36Sopenharmony_ci	qopt->cycle_time_extension = 1900000;
65162306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x96;
65262306a36Sopenharmony_ci	qopt->entries[0].interval = 400000;
65362306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x97;
65462306a36Sopenharmony_ci	qopt->entries[1].interval = 1600000;
65562306a36Sopenharmony_ci	qopt->num_entries = 2;
65662306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 9);
65762306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
65862306a36Sopenharmony_ci		goto failed;
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	/* change to different phase and shorter cycle time */
66162306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
66262306a36Sopenharmony_ci	qopt->cycle_time = 1500000;
66362306a36Sopenharmony_ci	qopt->cycle_time_extension = 700000;
66462306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x98;
66562306a36Sopenharmony_ci	qopt->entries[0].interval = 400000;
66662306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x99;
66762306a36Sopenharmony_ci	qopt->entries[1].interval = 600000;
66862306a36Sopenharmony_ci	qopt->entries[2].gate_mask = 0x9A;
66962306a36Sopenharmony_ci	qopt->entries[2].interval = 500000;
67062306a36Sopenharmony_ci	qopt->num_entries = 3;
67162306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 3);
67262306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
67362306a36Sopenharmony_ci		goto failed;
67462306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 100000);
67562306a36Sopenharmony_ci	qopt->cycle_time = 500000;
67662306a36Sopenharmony_ci	qopt->cycle_time_extension = 300000;
67762306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0x9B;
67862306a36Sopenharmony_ci	qopt->entries[0].interval = 150000;
67962306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0x9C;
68062306a36Sopenharmony_ci	qopt->entries[1].interval = 350000;
68162306a36Sopenharmony_ci	qopt->num_entries = 2;
68262306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 9);
68362306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
68462306a36Sopenharmony_ci		goto failed;
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci	/* change to different cycle time */
68762306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
68862306a36Sopenharmony_ci	qopt->cycle_time = 1000000;
68962306a36Sopenharmony_ci	qopt->cycle_time_extension = 700000;
69062306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0xAD;
69162306a36Sopenharmony_ci	qopt->entries[0].interval = 400000;
69262306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0xAE;
69362306a36Sopenharmony_ci	qopt->entries[1].interval = 300000;
69462306a36Sopenharmony_ci	qopt->entries[2].gate_mask = 0xAF;
69562306a36Sopenharmony_ci	qopt->entries[2].interval = 300000;
69662306a36Sopenharmony_ci	qopt->num_entries = 3;
69762306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
69862306a36Sopenharmony_ci		goto failed;
69962306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
70062306a36Sopenharmony_ci	qopt->cycle_time = 400000;
70162306a36Sopenharmony_ci	qopt->cycle_time_extension = 100000;
70262306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0xA0;
70362306a36Sopenharmony_ci	qopt->entries[0].interval = 200000;
70462306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0xA1;
70562306a36Sopenharmony_ci	qopt->entries[1].interval = 200000;
70662306a36Sopenharmony_ci	qopt->num_entries = 2;
70762306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 19);
70862306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
70962306a36Sopenharmony_ci		goto failed;
71062306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
71162306a36Sopenharmony_ci	qopt->cycle_time = 500000;
71262306a36Sopenharmony_ci	qopt->cycle_time_extension = 499999;
71362306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0xB2;
71462306a36Sopenharmony_ci	qopt->entries[0].interval = 100000;
71562306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0xB3;
71662306a36Sopenharmony_ci	qopt->entries[1].interval = 100000;
71762306a36Sopenharmony_ci	qopt->entries[2].gate_mask = 0xB4;
71862306a36Sopenharmony_ci	qopt->entries[2].interval = 100000;
71962306a36Sopenharmony_ci	qopt->entries[3].gate_mask = 0xB5;
72062306a36Sopenharmony_ci	qopt->entries[3].interval = 200000;
72162306a36Sopenharmony_ci	qopt->num_entries = 4;
72262306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 19);
72362306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
72462306a36Sopenharmony_ci		goto failed;
72562306a36Sopenharmony_ci	qopt->base_time = ktime_set(0, 0);
72662306a36Sopenharmony_ci	qopt->cycle_time = 6000000;
72762306a36Sopenharmony_ci	qopt->cycle_time_extension = 5999999;
72862306a36Sopenharmony_ci	qopt->entries[0].gate_mask = 0xC6;
72962306a36Sopenharmony_ci	qopt->entries[0].interval = 1000000;
73062306a36Sopenharmony_ci	qopt->entries[1].gate_mask = 0xC7;
73162306a36Sopenharmony_ci	qopt->entries[1].interval = 1000000;
73262306a36Sopenharmony_ci	qopt->entries[2].gate_mask = 0xC8;
73362306a36Sopenharmony_ci	qopt->entries[2].interval = 1000000;
73462306a36Sopenharmony_ci	qopt->entries[3].gate_mask = 0xC9;
73562306a36Sopenharmony_ci	qopt->entries[3].interval = 1500000;
73662306a36Sopenharmony_ci	qopt->entries[4].gate_mask = 0xCA;
73762306a36Sopenharmony_ci	qopt->entries[4].interval = 1500000;
73862306a36Sopenharmony_ci	qopt->num_entries = 5;
73962306a36Sopenharmony_ci	delay_base_time(adapter, qopt, 1);
74062306a36Sopenharmony_ci	if (!enable_check_taprio(adapter, qopt, 100))
74162306a36Sopenharmony_ci		goto failed;
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci	if (!disable_taprio(adapter))
74462306a36Sopenharmony_ci		goto failed;
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci	kfree(qopt);
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci	return true;
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_cifailed:
75162306a36Sopenharmony_ci	disable_taprio(adapter);
75262306a36Sopenharmony_ci	kfree(qopt);
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_ci	return false;
75562306a36Sopenharmony_ci}
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ciint tsnep_ethtool_get_test_count(void)
75862306a36Sopenharmony_ci{
75962306a36Sopenharmony_ci	return TSNEP_TEST_COUNT;
76062306a36Sopenharmony_ci}
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_civoid tsnep_ethtool_get_test_strings(u8 *data)
76362306a36Sopenharmony_ci{
76462306a36Sopenharmony_ci	memcpy(data, tsnep_test_strings, sizeof(tsnep_test_strings));
76562306a36Sopenharmony_ci}
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_civoid tsnep_ethtool_self_test(struct net_device *netdev,
76862306a36Sopenharmony_ci			     struct ethtool_test *eth_test, u64 *data)
76962306a36Sopenharmony_ci{
77062306a36Sopenharmony_ci	struct tsnep_adapter *adapter = netdev_priv(netdev);
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_ci	eth_test->len = TSNEP_TEST_COUNT;
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci	if (eth_test->flags != ETH_TEST_FL_OFFLINE) {
77562306a36Sopenharmony_ci		/* no tests are done online */
77662306a36Sopenharmony_ci		data[TSNEP_TEST_ENABLE] = 0;
77762306a36Sopenharmony_ci		data[TSNEP_TEST_TAPRIO] = 0;
77862306a36Sopenharmony_ci		data[TSNEP_TEST_TAPRIO_CHANGE] = 0;
77962306a36Sopenharmony_ci		data[TSNEP_TEST_TAPRIO_EXTENSION] = 0;
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_ci		return;
78262306a36Sopenharmony_ci	}
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_ci	if (tsnep_test_gc_enable(adapter)) {
78562306a36Sopenharmony_ci		data[TSNEP_TEST_ENABLE] = 0;
78662306a36Sopenharmony_ci	} else {
78762306a36Sopenharmony_ci		eth_test->flags |= ETH_TEST_FL_FAILED;
78862306a36Sopenharmony_ci		data[TSNEP_TEST_ENABLE] = 1;
78962306a36Sopenharmony_ci	}
79062306a36Sopenharmony_ci
79162306a36Sopenharmony_ci	if (tsnep_test_taprio(adapter)) {
79262306a36Sopenharmony_ci		data[TSNEP_TEST_TAPRIO] = 0;
79362306a36Sopenharmony_ci	} else {
79462306a36Sopenharmony_ci		eth_test->flags |= ETH_TEST_FL_FAILED;
79562306a36Sopenharmony_ci		data[TSNEP_TEST_TAPRIO] = 1;
79662306a36Sopenharmony_ci	}
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ci	if (tsnep_test_taprio_change(adapter)) {
79962306a36Sopenharmony_ci		data[TSNEP_TEST_TAPRIO_CHANGE] = 0;
80062306a36Sopenharmony_ci	} else {
80162306a36Sopenharmony_ci		eth_test->flags |= ETH_TEST_FL_FAILED;
80262306a36Sopenharmony_ci		data[TSNEP_TEST_TAPRIO_CHANGE] = 1;
80362306a36Sopenharmony_ci	}
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci	if (tsnep_test_taprio_extension(adapter)) {
80662306a36Sopenharmony_ci		data[TSNEP_TEST_TAPRIO_EXTENSION] = 0;
80762306a36Sopenharmony_ci	} else {
80862306a36Sopenharmony_ci		eth_test->flags |= ETH_TEST_FL_FAILED;
80962306a36Sopenharmony_ci		data[TSNEP_TEST_TAPRIO_EXTENSION] = 1;
81062306a36Sopenharmony_ci	}
81162306a36Sopenharmony_ci}
812