brintos

brintos / linux-shallow public Read only

0
0
Text · 21.3 KiB · 8a9145f Raw
812 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (C) 2021 Gerhard Engleder <gerhard@engleder-embedded.com> */3 4#include "tsnep.h"5 6#include <net/pkt_sched.h>7 8enum tsnep_test {9	TSNEP_TEST_ENABLE = 0,10	TSNEP_TEST_TAPRIO,11	TSNEP_TEST_TAPRIO_CHANGE,12	TSNEP_TEST_TAPRIO_EXTENSION,13};14 15static const char tsnep_test_strings[][ETH_GSTRING_LEN] = {16	"Enable timeout        (offline)",17	"TAPRIO                (offline)",18	"TAPRIO change         (offline)",19	"TAPRIO extension      (offline)",20};21 22#define TSNEP_TEST_COUNT (sizeof(tsnep_test_strings) / ETH_GSTRING_LEN)23 24static bool enable_gc_timeout(struct tsnep_adapter *adapter)25{26	iowrite8(TSNEP_GC_ENABLE_TIMEOUT, adapter->addr + TSNEP_GC);27	if (!(ioread32(adapter->addr + TSNEP_GC) & TSNEP_GC_TIMEOUT_ACTIVE))28		return false;29 30	return true;31}32 33static bool gc_timeout_signaled(struct tsnep_adapter *adapter)34{35	if (ioread32(adapter->addr + TSNEP_GC) & TSNEP_GC_TIMEOUT_SIGNAL)36		return true;37 38	return false;39}40 41static bool ack_gc_timeout(struct tsnep_adapter *adapter)42{43	iowrite8(TSNEP_GC_ENABLE_TIMEOUT, adapter->addr + TSNEP_GC);44	if (ioread32(adapter->addr + TSNEP_GC) &45	    (TSNEP_GC_TIMEOUT_ACTIVE | TSNEP_GC_TIMEOUT_SIGNAL))46		return false;47	return true;48}49 50static bool enable_gc(struct tsnep_adapter *adapter, bool a)51{52	u8 enable;53	u8 active;54 55	if (a) {56		enable = TSNEP_GC_ENABLE_A;57		active = TSNEP_GC_ACTIVE_A;58	} else {59		enable = TSNEP_GC_ENABLE_B;60		active = TSNEP_GC_ACTIVE_B;61	}62 63	iowrite8(enable, adapter->addr + TSNEP_GC);64	if (!(ioread32(adapter->addr + TSNEP_GC) & active))65		return false;66 67	return true;68}69 70static bool disable_gc(struct tsnep_adapter *adapter)71{72	iowrite8(TSNEP_GC_DISABLE, adapter->addr + TSNEP_GC);73	if (ioread32(adapter->addr + TSNEP_GC) &74	    (TSNEP_GC_ACTIVE_A | TSNEP_GC_ACTIVE_B))75		return false;76 77	return true;78}79 80static bool gc_delayed_enable(struct tsnep_adapter *adapter, bool a, int delay)81{82	u64 before, after;83	u32 time;84	bool enabled;85 86	if (!disable_gc(adapter))87		return false;88 89	before = ktime_get_ns();90 91	if (!enable_gc_timeout(adapter))92		return false;93 94	/* for start time after timeout, the timeout can guarantee, that enable95	 * is blocked if too late96	 */97	time = ioread32(adapter->addr + ECM_SYSTEM_TIME_LOW);98	time += TSNEP_GC_TIMEOUT;99	iowrite32(time, adapter->addr + TSNEP_GC_TIME);100 101	ndelay(delay);102 103	enabled = enable_gc(adapter, a);104	after = ktime_get_ns();105 106	if (delay > TSNEP_GC_TIMEOUT) {107		/* timeout must have blocked enable */108		if (enabled)109			return false;110	} else if ((after - before) < TSNEP_GC_TIMEOUT * 14 / 16) {111		/* timeout must not have blocked enable */112		if (!enabled)113			return false;114	}115 116	if (enabled) {117		if (gc_timeout_signaled(adapter))118			return false;119	} else {120		if (!gc_timeout_signaled(adapter))121			return false;122		if (!ack_gc_timeout(adapter))123			return false;124	}125 126	if (!disable_gc(adapter))127		return false;128 129	return true;130}131 132static bool tsnep_test_gc_enable(struct tsnep_adapter *adapter)133{134	int i;135 136	iowrite32(0x80000001, adapter->addr + TSNEP_GCL_A + 0);137	iowrite32(100000, adapter->addr + TSNEP_GCL_A + 4);138 139	for (i = 0; i < 200000; i += 100) {140		if (!gc_delayed_enable(adapter, true, i))141			return false;142	}143 144	iowrite32(0x80000001, adapter->addr + TSNEP_GCL_B + 0);145	iowrite32(100000, adapter->addr + TSNEP_GCL_B + 4);146 147	for (i = 0; i < 200000; i += 100) {148		if (!gc_delayed_enable(adapter, false, i))149			return false;150	}151 152	return true;153}154 155static void delay_base_time(struct tsnep_adapter *adapter,156			    struct tc_taprio_qopt_offload *qopt, s64 ms)157{158	u64 system_time;159	u64 base_time = ktime_to_ns(qopt->base_time);160	u64 n;161 162	tsnep_get_system_time(adapter, &system_time);163	system_time += ms * 1000000;164	n = div64_u64(system_time - base_time, qopt->cycle_time);165 166	qopt->base_time = ktime_add_ns(qopt->base_time,167				       (n + 1) * qopt->cycle_time);168}169 170static void get_gate_state(struct tsnep_adapter *adapter, u32 *gc, u32 *gc_time,171			   u64 *system_time)172{173	u32 time_high_before;174	u32 time_low;175	u32 time_high;176	u32 gc_time_before;177 178	time_high = ioread32(adapter->addr + ECM_SYSTEM_TIME_HIGH);179	*gc_time = ioread32(adapter->addr + TSNEP_GC_TIME);180	do {181		time_low = ioread32(adapter->addr + ECM_SYSTEM_TIME_LOW);182		*gc = ioread32(adapter->addr + TSNEP_GC);183 184		gc_time_before = *gc_time;185		*gc_time = ioread32(adapter->addr + TSNEP_GC_TIME);186		time_high_before = time_high;187		time_high = ioread32(adapter->addr + ECM_SYSTEM_TIME_HIGH);188	} while ((time_high != time_high_before) ||189		 (*gc_time != gc_time_before));190 191	*system_time = (((u64)time_high) << 32) | ((u64)time_low);192}193 194static int get_operation(struct tsnep_gcl *gcl, u64 system_time, u64 *next)195{196	u64 n = div64_u64(system_time - gcl->base_time, gcl->cycle_time);197	u64 cycle_start = gcl->base_time + gcl->cycle_time * n;198	int i;199 200	*next = cycle_start;201	for (i = 0; i < gcl->count; i++) {202		*next += gcl->operation[i].interval;203		if (*next > system_time)204			break;205	}206 207	return i;208}209 210static bool check_gate(struct tsnep_adapter *adapter)211{212	u32 gc_time;213	u32 gc;214	u64 system_time;215	struct tsnep_gcl *curr;216	struct tsnep_gcl *prev;217	u64 next_time;218	u8 gate_open;219	u8 next_gate_open;220 221	get_gate_state(adapter, &gc, &gc_time, &system_time);222 223	if (gc & TSNEP_GC_ACTIVE_A) {224		curr = &adapter->gcl[0];225		prev = &adapter->gcl[1];226	} else if (gc & TSNEP_GC_ACTIVE_B) {227		curr = &adapter->gcl[1];228		prev = &adapter->gcl[0];229	} else {230		return false;231	}232	if (curr->start_time <= system_time) {233		/* GCL is already active */234		int index;235 236		index = get_operation(curr, system_time, &next_time);237		gate_open = curr->operation[index].properties & TSNEP_GCL_MASK;238		if (index == curr->count - 1)239			index = 0;240		else241			index++;242		next_gate_open =243			curr->operation[index].properties & TSNEP_GCL_MASK;244	} else if (curr->change) {245		/* operation of previous GCL is active */246		int index;247		u64 start_before;248		u64 n;249 250		index = get_operation(prev, system_time, &next_time);251		next_time = curr->start_time;252		start_before = prev->base_time;253		n = div64_u64(curr->start_time - start_before,254			      prev->cycle_time);255		start_before += n * prev->cycle_time;256		if (curr->start_time == start_before)257			start_before -= prev->cycle_time;258		if (((start_before + prev->cycle_time_extension) >=259		     curr->start_time) &&260		    (curr->start_time - prev->cycle_time_extension <=261		     system_time)) {262			/* extend */263			index = prev->count - 1;264		}265		gate_open = prev->operation[index].properties & TSNEP_GCL_MASK;266		next_gate_open =267			curr->operation[0].properties & TSNEP_GCL_MASK;268	} else {269		/* GCL is waiting for start */270		next_time = curr->start_time;271		gate_open = 0xFF;272		next_gate_open = curr->operation[0].properties & TSNEP_GCL_MASK;273	}274 275	if (gc_time != (next_time & 0xFFFFFFFF)) {276		dev_err(&adapter->pdev->dev, "gate control time 0x%x!=0x%llx\n",277			gc_time, next_time);278		return false;279	}280	if (((gc & TSNEP_GC_OPEN) >> TSNEP_GC_OPEN_SHIFT) != gate_open) {281		dev_err(&adapter->pdev->dev,282			"gate control open 0x%02x!=0x%02x\n",283			((gc & TSNEP_GC_OPEN) >> TSNEP_GC_OPEN_SHIFT),284			gate_open);285		return false;286	}287	if (((gc & TSNEP_GC_NEXT_OPEN) >> TSNEP_GC_NEXT_OPEN_SHIFT) !=288	    next_gate_open) {289		dev_err(&adapter->pdev->dev,290			"gate control next open 0x%02x!=0x%02x\n",291			((gc & TSNEP_GC_NEXT_OPEN) >> TSNEP_GC_NEXT_OPEN_SHIFT),292			next_gate_open);293		return false;294	}295 296	return true;297}298 299static bool check_gate_duration(struct tsnep_adapter *adapter, s64 ms)300{301	ktime_t start = ktime_get();302 303	do {304		if (!check_gate(adapter))305			return false;306	} while (ktime_ms_delta(ktime_get(), start) < ms);307 308	return true;309}310 311static bool enable_check_taprio(struct tsnep_adapter *adapter,312				struct tc_taprio_qopt_offload *qopt, s64 ms)313{314	int retval;315 316	retval = tsnep_tc_setup(adapter->netdev, TC_SETUP_QDISC_TAPRIO, qopt);317	if (retval)318		return false;319 320	if (!check_gate_duration(adapter, ms))321		return false;322 323	return true;324}325 326static bool disable_taprio(struct tsnep_adapter *adapter)327{328	struct tc_taprio_qopt_offload qopt;329	int retval;330 331	memset(&qopt, 0, sizeof(qopt));332	qopt.cmd = TAPRIO_CMD_DESTROY;333	retval = tsnep_tc_setup(adapter->netdev, TC_SETUP_QDISC_TAPRIO, &qopt);334	if (retval)335		return false;336 337	return true;338}339 340static bool run_taprio(struct tsnep_adapter *adapter,341		       struct tc_taprio_qopt_offload *qopt, s64 ms)342{343	if (!enable_check_taprio(adapter, qopt, ms))344		return false;345 346	if (!disable_taprio(adapter))347		return false;348 349	return true;350}351 352static bool tsnep_test_taprio(struct tsnep_adapter *adapter)353{354	struct tc_taprio_qopt_offload *qopt;355	int i;356 357	qopt = kzalloc(struct_size(qopt, entries, 255), GFP_KERNEL);358	if (!qopt)359		return false;360	for (i = 0; i < 255; i++)361		qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES;362 363	qopt->cmd = TAPRIO_CMD_REPLACE;364	qopt->base_time = ktime_set(0, 0);365	qopt->cycle_time = 1500000;366	qopt->cycle_time_extension = 0;367	qopt->entries[0].gate_mask = 0x02;368	qopt->entries[0].interval = 200000;369	qopt->entries[1].gate_mask = 0x03;370	qopt->entries[1].interval = 800000;371	qopt->entries[2].gate_mask = 0x07;372	qopt->entries[2].interval = 240000;373	qopt->entries[3].gate_mask = 0x01;374	qopt->entries[3].interval = 80000;375	qopt->entries[4].gate_mask = 0x04;376	qopt->entries[4].interval = 70000;377	qopt->entries[5].gate_mask = 0x06;378	qopt->entries[5].interval = 60000;379	qopt->entries[6].gate_mask = 0x0F;380	qopt->entries[6].interval = 50000;381	qopt->num_entries = 7;382	if (!run_taprio(adapter, qopt, 100))383		goto failed;384 385	qopt->cmd = TAPRIO_CMD_REPLACE;386	qopt->base_time = ktime_set(0, 0);387	qopt->cycle_time = 411854;388	qopt->cycle_time_extension = 0;389	qopt->entries[0].gate_mask = 0x17;390	qopt->entries[0].interval = 23842;391	qopt->entries[1].gate_mask = 0x16;392	qopt->entries[1].interval = 13482;393	qopt->entries[2].gate_mask = 0x15;394	qopt->entries[2].interval = 49428;395	qopt->entries[3].gate_mask = 0x14;396	qopt->entries[3].interval = 38189;397	qopt->entries[4].gate_mask = 0x13;398	qopt->entries[4].interval = 92321;399	qopt->entries[5].gate_mask = 0x12;400	qopt->entries[5].interval = 71239;401	qopt->entries[6].gate_mask = 0x11;402	qopt->entries[6].interval = 69932;403	qopt->entries[7].gate_mask = 0x10;404	qopt->entries[7].interval = 53421;405	qopt->num_entries = 8;406	if (!run_taprio(adapter, qopt, 100))407		goto failed;408 409	qopt->cmd = TAPRIO_CMD_REPLACE;410	qopt->base_time = ktime_set(0, 0);411	delay_base_time(adapter, qopt, 12);412	qopt->cycle_time = 125000;413	qopt->cycle_time_extension = 0;414	qopt->entries[0].gate_mask = 0x27;415	qopt->entries[0].interval = 15000;416	qopt->entries[1].gate_mask = 0x26;417	qopt->entries[1].interval = 15000;418	qopt->entries[2].gate_mask = 0x25;419	qopt->entries[2].interval = 12500;420	qopt->entries[3].gate_mask = 0x24;421	qopt->entries[3].interval = 17500;422	qopt->entries[4].gate_mask = 0x23;423	qopt->entries[4].interval = 10000;424	qopt->entries[5].gate_mask = 0x22;425	qopt->entries[5].interval = 11000;426	qopt->entries[6].gate_mask = 0x21;427	qopt->entries[6].interval = 9000;428	qopt->entries[7].gate_mask = 0x20;429	qopt->entries[7].interval = 10000;430	qopt->entries[8].gate_mask = 0x20;431	qopt->entries[8].interval = 12500;432	qopt->entries[9].gate_mask = 0x20;433	qopt->entries[9].interval = 12500;434	qopt->num_entries = 10;435	if (!run_taprio(adapter, qopt, 100))436		goto failed;437 438	kfree(qopt);439 440	return true;441 442failed:443	disable_taprio(adapter);444	kfree(qopt);445 446	return false;447}448 449static bool tsnep_test_taprio_change(struct tsnep_adapter *adapter)450{451	struct tc_taprio_qopt_offload *qopt;452	int i;453 454	qopt = kzalloc(struct_size(qopt, entries, 255), GFP_KERNEL);455	if (!qopt)456		return false;457	for (i = 0; i < 255; i++)458		qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES;459 460	qopt->cmd = TAPRIO_CMD_REPLACE;461	qopt->base_time = ktime_set(0, 0);462	qopt->cycle_time = 100000;463	qopt->cycle_time_extension = 0;464	qopt->entries[0].gate_mask = 0x30;465	qopt->entries[0].interval = 20000;466	qopt->entries[1].gate_mask = 0x31;467	qopt->entries[1].interval = 80000;468	qopt->num_entries = 2;469	if (!enable_check_taprio(adapter, qopt, 100))470		goto failed;471 472	/* change to identical */473	if (!enable_check_taprio(adapter, qopt, 100))474		goto failed;475	delay_base_time(adapter, qopt, 17);476	if (!enable_check_taprio(adapter, qopt, 100))477		goto failed;478 479	/* change to same cycle time */480	qopt->base_time = ktime_set(0, 0);481	qopt->entries[0].gate_mask = 0x42;482	qopt->entries[1].gate_mask = 0x43;483	delay_base_time(adapter, qopt, 2);484	if (!enable_check_taprio(adapter, qopt, 100))485		goto failed;486	qopt->base_time = ktime_set(0, 0);487	qopt->entries[0].gate_mask = 0x54;488	qopt->entries[0].interval = 33333;489	qopt->entries[1].gate_mask = 0x55;490	qopt->entries[1].interval = 66667;491	delay_base_time(adapter, qopt, 23);492	if (!enable_check_taprio(adapter, qopt, 100))493		goto failed;494	qopt->base_time = ktime_set(0, 0);495	qopt->entries[0].gate_mask = 0x66;496	qopt->entries[0].interval = 50000;497	qopt->entries[1].gate_mask = 0x67;498	qopt->entries[1].interval = 25000;499	qopt->entries[2].gate_mask = 0x68;500	qopt->entries[2].interval = 25000;501	qopt->num_entries = 3;502	delay_base_time(adapter, qopt, 11);503	if (!enable_check_taprio(adapter, qopt, 100))504		goto failed;505 506	/* change to multiple of cycle time */507	qopt->base_time = ktime_set(0, 0);508	qopt->cycle_time = 200000;509	qopt->entries[0].gate_mask = 0x79;510	qopt->entries[0].interval = 50000;511	qopt->entries[1].gate_mask = 0x7A;512	qopt->entries[1].interval = 150000;513	qopt->num_entries = 2;514	delay_base_time(adapter, qopt, 11);515	if (!enable_check_taprio(adapter, qopt, 100))516		goto failed;517	qopt->base_time = ktime_set(0, 0);518	qopt->cycle_time = 1000000;519	qopt->entries[0].gate_mask = 0x7B;520	qopt->entries[0].interval = 125000;521	qopt->entries[1].gate_mask = 0x7C;522	qopt->entries[1].interval = 250000;523	qopt->entries[2].gate_mask = 0x7D;524	qopt->entries[2].interval = 375000;525	qopt->entries[3].gate_mask = 0x7E;526	qopt->entries[3].interval = 250000;527	qopt->num_entries = 4;528	delay_base_time(adapter, qopt, 3);529	if (!enable_check_taprio(adapter, qopt, 100))530		goto failed;531 532	/* change to shorter cycle time */533	qopt->base_time = ktime_set(0, 0);534	qopt->cycle_time = 333333;535	qopt->entries[0].gate_mask = 0x8F;536	qopt->entries[0].interval = 166666;537	qopt->entries[1].gate_mask = 0x80;538	qopt->entries[1].interval = 166667;539	qopt->num_entries = 2;540	delay_base_time(adapter, qopt, 11);541	if (!enable_check_taprio(adapter, qopt, 100))542		goto failed;543	qopt->base_time = ktime_set(0, 0);544	qopt->cycle_time = 62500;545	qopt->entries[0].gate_mask = 0x81;546	qopt->entries[0].interval = 31250;547	qopt->entries[1].gate_mask = 0x82;548	qopt->entries[1].interval = 15625;549	qopt->entries[2].gate_mask = 0x83;550	qopt->entries[2].interval = 15625;551	qopt->num_entries = 3;552	delay_base_time(adapter, qopt, 1);553	if (!enable_check_taprio(adapter, qopt, 100))554		goto failed;555 556	/* change to longer cycle time */557	qopt->base_time = ktime_set(0, 0);558	qopt->cycle_time = 400000;559	qopt->entries[0].gate_mask = 0x84;560	qopt->entries[0].interval = 100000;561	qopt->entries[1].gate_mask = 0x85;562	qopt->entries[1].interval = 100000;563	qopt->entries[2].gate_mask = 0x86;564	qopt->entries[2].interval = 100000;565	qopt->entries[3].gate_mask = 0x87;566	qopt->entries[3].interval = 100000;567	qopt->num_entries = 4;568	delay_base_time(adapter, qopt, 7);569	if (!enable_check_taprio(adapter, qopt, 100))570		goto failed;571	qopt->base_time = ktime_set(0, 0);572	qopt->cycle_time = 1700000;573	qopt->entries[0].gate_mask = 0x88;574	qopt->entries[0].interval = 200000;575	qopt->entries[1].gate_mask = 0x89;576	qopt->entries[1].interval = 300000;577	qopt->entries[2].gate_mask = 0x8A;578	qopt->entries[2].interval = 600000;579	qopt->entries[3].gate_mask = 0x8B;580	qopt->entries[3].interval = 100000;581	qopt->entries[4].gate_mask = 0x8C;582	qopt->entries[4].interval = 500000;583	qopt->num_entries = 5;584	delay_base_time(adapter, qopt, 6);585	if (!enable_check_taprio(adapter, qopt, 100))586		goto failed;587 588	if (!disable_taprio(adapter))589		goto failed;590 591	kfree(qopt);592 593	return true;594 595failed:596	disable_taprio(adapter);597	kfree(qopt);598 599	return false;600}601 602static bool tsnep_test_taprio_extension(struct tsnep_adapter *adapter)603{604	struct tc_taprio_qopt_offload *qopt;605	int i;606 607	qopt = kzalloc(struct_size(qopt, entries, 255), GFP_KERNEL);608	if (!qopt)609		return false;610	for (i = 0; i < 255; i++)611		qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES;612 613	qopt->cmd = TAPRIO_CMD_REPLACE;614	qopt->base_time = ktime_set(0, 0);615	qopt->cycle_time = 100000;616	qopt->cycle_time_extension = 50000;617	qopt->entries[0].gate_mask = 0x90;618	qopt->entries[0].interval = 20000;619	qopt->entries[1].gate_mask = 0x91;620	qopt->entries[1].interval = 80000;621	qopt->num_entries = 2;622	if (!enable_check_taprio(adapter, qopt, 100))623		goto failed;624 625	/* change to different phase */626	qopt->base_time = ktime_set(0, 50000);627	qopt->entries[0].gate_mask = 0x92;628	qopt->entries[0].interval = 33000;629	qopt->entries[1].gate_mask = 0x93;630	qopt->entries[1].interval = 67000;631	qopt->num_entries = 2;632	delay_base_time(adapter, qopt, 2);633	if (!enable_check_taprio(adapter, qopt, 100))634		goto failed;635 636	/* change to different phase and longer cycle time */637	qopt->base_time = ktime_set(0, 0);638	qopt->cycle_time = 1000000;639	qopt->cycle_time_extension = 700000;640	qopt->entries[0].gate_mask = 0x94;641	qopt->entries[0].interval = 400000;642	qopt->entries[1].gate_mask = 0x95;643	qopt->entries[1].interval = 600000;644	qopt->num_entries = 2;645	delay_base_time(adapter, qopt, 7);646	if (!enable_check_taprio(adapter, qopt, 100))647		goto failed;648	qopt->base_time = ktime_set(0, 700000);649	qopt->cycle_time = 2000000;650	qopt->cycle_time_extension = 1900000;651	qopt->entries[0].gate_mask = 0x96;652	qopt->entries[0].interval = 400000;653	qopt->entries[1].gate_mask = 0x97;654	qopt->entries[1].interval = 1600000;655	qopt->num_entries = 2;656	delay_base_time(adapter, qopt, 9);657	if (!enable_check_taprio(adapter, qopt, 100))658		goto failed;659 660	/* change to different phase and shorter cycle time */661	qopt->base_time = ktime_set(0, 0);662	qopt->cycle_time = 1500000;663	qopt->cycle_time_extension = 700000;664	qopt->entries[0].gate_mask = 0x98;665	qopt->entries[0].interval = 400000;666	qopt->entries[1].gate_mask = 0x99;667	qopt->entries[1].interval = 600000;668	qopt->entries[2].gate_mask = 0x9A;669	qopt->entries[2].interval = 500000;670	qopt->num_entries = 3;671	delay_base_time(adapter, qopt, 3);672	if (!enable_check_taprio(adapter, qopt, 100))673		goto failed;674	qopt->base_time = ktime_set(0, 100000);675	qopt->cycle_time = 500000;676	qopt->cycle_time_extension = 300000;677	qopt->entries[0].gate_mask = 0x9B;678	qopt->entries[0].interval = 150000;679	qopt->entries[1].gate_mask = 0x9C;680	qopt->entries[1].interval = 350000;681	qopt->num_entries = 2;682	delay_base_time(adapter, qopt, 9);683	if (!enable_check_taprio(adapter, qopt, 100))684		goto failed;685 686	/* change to different cycle time */687	qopt->base_time = ktime_set(0, 0);688	qopt->cycle_time = 1000000;689	qopt->cycle_time_extension = 700000;690	qopt->entries[0].gate_mask = 0xAD;691	qopt->entries[0].interval = 400000;692	qopt->entries[1].gate_mask = 0xAE;693	qopt->entries[1].interval = 300000;694	qopt->entries[2].gate_mask = 0xAF;695	qopt->entries[2].interval = 300000;696	qopt->num_entries = 3;697	if (!enable_check_taprio(adapter, qopt, 100))698		goto failed;699	qopt->base_time = ktime_set(0, 0);700	qopt->cycle_time = 400000;701	qopt->cycle_time_extension = 100000;702	qopt->entries[0].gate_mask = 0xA0;703	qopt->entries[0].interval = 200000;704	qopt->entries[1].gate_mask = 0xA1;705	qopt->entries[1].interval = 200000;706	qopt->num_entries = 2;707	delay_base_time(adapter, qopt, 19);708	if (!enable_check_taprio(adapter, qopt, 100))709		goto failed;710	qopt->base_time = ktime_set(0, 0);711	qopt->cycle_time = 500000;712	qopt->cycle_time_extension = 499999;713	qopt->entries[0].gate_mask = 0xB2;714	qopt->entries[0].interval = 100000;715	qopt->entries[1].gate_mask = 0xB3;716	qopt->entries[1].interval = 100000;717	qopt->entries[2].gate_mask = 0xB4;718	qopt->entries[2].interval = 100000;719	qopt->entries[3].gate_mask = 0xB5;720	qopt->entries[3].interval = 200000;721	qopt->num_entries = 4;722	delay_base_time(adapter, qopt, 19);723	if (!enable_check_taprio(adapter, qopt, 100))724		goto failed;725	qopt->base_time = ktime_set(0, 0);726	qopt->cycle_time = 6000000;727	qopt->cycle_time_extension = 5999999;728	qopt->entries[0].gate_mask = 0xC6;729	qopt->entries[0].interval = 1000000;730	qopt->entries[1].gate_mask = 0xC7;731	qopt->entries[1].interval = 1000000;732	qopt->entries[2].gate_mask = 0xC8;733	qopt->entries[2].interval = 1000000;734	qopt->entries[3].gate_mask = 0xC9;735	qopt->entries[3].interval = 1500000;736	qopt->entries[4].gate_mask = 0xCA;737	qopt->entries[4].interval = 1500000;738	qopt->num_entries = 5;739	delay_base_time(adapter, qopt, 1);740	if (!enable_check_taprio(adapter, qopt, 100))741		goto failed;742 743	if (!disable_taprio(adapter))744		goto failed;745 746	kfree(qopt);747 748	return true;749 750failed:751	disable_taprio(adapter);752	kfree(qopt);753 754	return false;755}756 757int tsnep_ethtool_get_test_count(void)758{759	return TSNEP_TEST_COUNT;760}761 762void tsnep_ethtool_get_test_strings(u8 *data)763{764	memcpy(data, tsnep_test_strings, sizeof(tsnep_test_strings));765}766 767void tsnep_ethtool_self_test(struct net_device *netdev,768			     struct ethtool_test *eth_test, u64 *data)769{770	struct tsnep_adapter *adapter = netdev_priv(netdev);771 772	eth_test->len = TSNEP_TEST_COUNT;773 774	if (eth_test->flags != ETH_TEST_FL_OFFLINE) {775		/* no tests are done online */776		data[TSNEP_TEST_ENABLE] = 0;777		data[TSNEP_TEST_TAPRIO] = 0;778		data[TSNEP_TEST_TAPRIO_CHANGE] = 0;779		data[TSNEP_TEST_TAPRIO_EXTENSION] = 0;780 781		return;782	}783 784	if (tsnep_test_gc_enable(adapter)) {785		data[TSNEP_TEST_ENABLE] = 0;786	} else {787		eth_test->flags |= ETH_TEST_FL_FAILED;788		data[TSNEP_TEST_ENABLE] = 1;789	}790 791	if (tsnep_test_taprio(adapter)) {792		data[TSNEP_TEST_TAPRIO] = 0;793	} else {794		eth_test->flags |= ETH_TEST_FL_FAILED;795		data[TSNEP_TEST_TAPRIO] = 1;796	}797 798	if (tsnep_test_taprio_change(adapter)) {799		data[TSNEP_TEST_TAPRIO_CHANGE] = 0;800	} else {801		eth_test->flags |= ETH_TEST_FL_FAILED;802		data[TSNEP_TEST_TAPRIO_CHANGE] = 1;803	}804 805	if (tsnep_test_taprio_extension(adapter)) {806		data[TSNEP_TEST_TAPRIO_EXTENSION] = 0;807	} else {808		eth_test->flags |= ETH_TEST_FL_FAILED;809		data[TSNEP_TEST_TAPRIO_EXTENSION] = 1;810	}811}812