cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tsnep_selftests.c (21727B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* 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 enable
     95	 * is blocked if too late
     96	 */
     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		else
    241			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.enable = 0;
    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->enable = 1;
    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->enable = 1;
    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->enable = 1;
    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->enable = 1;
    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->enable = 1;
    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}