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, a: true, delay: 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, a: false, delay: 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(kt: qopt->base_time);
160 u64 n;
161
162 tsnep_get_system_time(adapter, time: &system_time);
163 system_time += ms * 1000000;
164 n = div64_u64(dividend: system_time - base_time, divisor: 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(dividend: system_time - gcl->base_time, divisor: 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, gc_time: &gc_time, system_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(gcl: curr, system_time, next: &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(gcl: prev, system_time, next: &next_time);
251 next_time = curr->start_time;
252 start_before = prev->base_time;
253 n = div64_u64(dividend: curr->start_time - start_before,
254 divisor: 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(later: ktime_get(), earlier: 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(netdev: adapter->netdev, type: TC_SETUP_QDISC_TAPRIO, type_data: 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(netdev: adapter->netdev, type: TC_SETUP_QDISC_TAPRIO, type_data: &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(secs: 0, nsecs: 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, ms: 100))
383 goto failed;
384
385 qopt->cmd = TAPRIO_CMD_REPLACE;
386 qopt->base_time = ktime_set(secs: 0, nsecs: 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, ms: 100))
407 goto failed;
408
409 qopt->cmd = TAPRIO_CMD_REPLACE;
410 qopt->base_time = ktime_set(secs: 0, nsecs: 0);
411 delay_base_time(adapter, qopt, ms: 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, ms: 100))
436 goto failed;
437
438 kfree(objp: qopt);
439
440 return true;
441
442failed:
443 disable_taprio(adapter);
444 kfree(objp: 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(secs: 0, nsecs: 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, ms: 100))
470 goto failed;
471
472 /* change to identical */
473 if (!enable_check_taprio(adapter, qopt, ms: 100))
474 goto failed;
475 delay_base_time(adapter, qopt, ms: 17);
476 if (!enable_check_taprio(adapter, qopt, ms: 100))
477 goto failed;
478
479 /* change to same cycle time */
480 qopt->base_time = ktime_set(secs: 0, nsecs: 0);
481 qopt->entries[0].gate_mask = 0x42;
482 qopt->entries[1].gate_mask = 0x43;
483 delay_base_time(adapter, qopt, ms: 2);
484 if (!enable_check_taprio(adapter, qopt, ms: 100))
485 goto failed;
486 qopt->base_time = ktime_set(secs: 0, nsecs: 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, ms: 23);
492 if (!enable_check_taprio(adapter, qopt, ms: 100))
493 goto failed;
494 qopt->base_time = ktime_set(secs: 0, nsecs: 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, ms: 11);
503 if (!enable_check_taprio(adapter, qopt, ms: 100))
504 goto failed;
505
506 /* change to multiple of cycle time */
507 qopt->base_time = ktime_set(secs: 0, nsecs: 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, ms: 11);
515 if (!enable_check_taprio(adapter, qopt, ms: 100))
516 goto failed;
517 qopt->base_time = ktime_set(secs: 0, nsecs: 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, ms: 3);
529 if (!enable_check_taprio(adapter, qopt, ms: 100))
530 goto failed;
531
532 /* change to shorter cycle time */
533 qopt->base_time = ktime_set(secs: 0, nsecs: 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, ms: 11);
541 if (!enable_check_taprio(adapter, qopt, ms: 100))
542 goto failed;
543 qopt->base_time = ktime_set(secs: 0, nsecs: 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, ms: 1);
553 if (!enable_check_taprio(adapter, qopt, ms: 100))
554 goto failed;
555
556 /* change to longer cycle time */
557 qopt->base_time = ktime_set(secs: 0, nsecs: 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, ms: 7);
569 if (!enable_check_taprio(adapter, qopt, ms: 100))
570 goto failed;
571 qopt->base_time = ktime_set(secs: 0, nsecs: 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, ms: 6);
585 if (!enable_check_taprio(adapter, qopt, ms: 100))
586 goto failed;
587
588 if (!disable_taprio(adapter))
589 goto failed;
590
591 kfree(objp: qopt);
592
593 return true;
594
595failed:
596 disable_taprio(adapter);
597 kfree(objp: 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(secs: 0, nsecs: 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, ms: 100))
623 goto failed;
624
625 /* change to different phase */
626 qopt->base_time = ktime_set(secs: 0, nsecs: 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, ms: 2);
633 if (!enable_check_taprio(adapter, qopt, ms: 100))
634 goto failed;
635
636 /* change to different phase and longer cycle time */
637 qopt->base_time = ktime_set(secs: 0, nsecs: 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, ms: 7);
646 if (!enable_check_taprio(adapter, qopt, ms: 100))
647 goto failed;
648 qopt->base_time = ktime_set(secs: 0, nsecs: 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, ms: 9);
657 if (!enable_check_taprio(adapter, qopt, ms: 100))
658 goto failed;
659
660 /* change to different phase and shorter cycle time */
661 qopt->base_time = ktime_set(secs: 0, nsecs: 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, ms: 3);
672 if (!enable_check_taprio(adapter, qopt, ms: 100))
673 goto failed;
674 qopt->base_time = ktime_set(secs: 0, nsecs: 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, ms: 9);
683 if (!enable_check_taprio(adapter, qopt, ms: 100))
684 goto failed;
685
686 /* change to different cycle time */
687 qopt->base_time = ktime_set(secs: 0, nsecs: 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, ms: 100))
698 goto failed;
699 qopt->base_time = ktime_set(secs: 0, nsecs: 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, ms: 19);
708 if (!enable_check_taprio(adapter, qopt, ms: 100))
709 goto failed;
710 qopt->base_time = ktime_set(secs: 0, nsecs: 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, ms: 19);
723 if (!enable_check_taprio(adapter, qopt, ms: 100))
724 goto failed;
725 qopt->base_time = ktime_set(secs: 0, nsecs: 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, ms: 1);
740 if (!enable_check_taprio(adapter, qopt, ms: 100))
741 goto failed;
742
743 if (!disable_taprio(adapter))
744 goto failed;
745
746 kfree(objp: qopt);
747
748 return true;
749
750failed:
751 disable_taprio(adapter);
752 kfree(objp: 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(dev: 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

source code of linux/drivers/net/ethernet/engleder/tsnep_selftests.c