1bfacad7dSJoe Hershberger /*
2bfacad7dSJoe Hershberger * Copyright (c) 2015 National Instruments
3bfacad7dSJoe Hershberger *
4bfacad7dSJoe Hershberger * (C) Copyright 2015
5bfacad7dSJoe Hershberger * Joe Hershberger <joe.hershberger@ni.com>
6bfacad7dSJoe Hershberger *
7bfacad7dSJoe Hershberger * SPDX-License-Identifier: GPL-2.0
8bfacad7dSJoe Hershberger */
9bfacad7dSJoe Hershberger
10bfacad7dSJoe Hershberger #include <common.h>
11bfacad7dSJoe Hershberger #include <dm.h>
12bfacad7dSJoe Hershberger #include <fdtdec.h>
13bfacad7dSJoe Hershberger #include <malloc.h>
14bfacad7dSJoe Hershberger #include <net.h>
15e721b882SJoe Hershberger #include <dm/test.h>
166d9764c2SBin Meng #include <dm/device-internal.h>
176d9764c2SBin Meng #include <dm/uclass-internal.h>
187ece1c61SJoe Hershberger #include <asm/eth.h>
19e721b882SJoe Hershberger #include <test/ut.h>
20bfacad7dSJoe Hershberger
21bfacad7dSJoe Hershberger DECLARE_GLOBAL_DATA_PTR;
22bfacad7dSJoe Hershberger
236d9764c2SBin Meng #define DM_TEST_ETH_NUM 4
246d9764c2SBin Meng
dm_test_eth(struct unit_test_state * uts)25e721b882SJoe Hershberger static int dm_test_eth(struct unit_test_state *uts)
26bfacad7dSJoe Hershberger {
27049a95a7SJoe Hershberger net_ping_ip = string_to_ip("1.1.2.2");
28bfacad7dSJoe Hershberger
29382bee57SSimon Glass env_set("ethact", "eth@10002000");
30bc0571fcSJoe Hershberger ut_assertok(net_loop(PING));
31*00caae6dSSimon Glass ut_asserteq_str("eth@10002000", env_get("ethact"));
32bfacad7dSJoe Hershberger
33382bee57SSimon Glass env_set("ethact", "eth@10003000");
34bc0571fcSJoe Hershberger ut_assertok(net_loop(PING));
35*00caae6dSSimon Glass ut_asserteq_str("eth@10003000", env_get("ethact"));
36bfacad7dSJoe Hershberger
37382bee57SSimon Glass env_set("ethact", "eth@10004000");
38bc0571fcSJoe Hershberger ut_assertok(net_loop(PING));
39*00caae6dSSimon Glass ut_asserteq_str("eth@10004000", env_get("ethact"));
40bfacad7dSJoe Hershberger
41bfacad7dSJoe Hershberger return 0;
42bfacad7dSJoe Hershberger }
43bfacad7dSJoe Hershberger DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
44e58780dcSJoe Hershberger
dm_test_eth_alias(struct unit_test_state * uts)45e721b882SJoe Hershberger static int dm_test_eth_alias(struct unit_test_state *uts)
46e58780dcSJoe Hershberger {
47049a95a7SJoe Hershberger net_ping_ip = string_to_ip("1.1.2.2");
48382bee57SSimon Glass env_set("ethact", "eth0");
49bc0571fcSJoe Hershberger ut_assertok(net_loop(PING));
50*00caae6dSSimon Glass ut_asserteq_str("eth@10002000", env_get("ethact"));
51e58780dcSJoe Hershberger
52382bee57SSimon Glass env_set("ethact", "eth1");
53bc0571fcSJoe Hershberger ut_assertok(net_loop(PING));
54*00caae6dSSimon Glass ut_asserteq_str("eth@10004000", env_get("ethact"));
55e58780dcSJoe Hershberger
56e58780dcSJoe Hershberger /* Expected to fail since eth2 is not defined in the device tree */
57382bee57SSimon Glass env_set("ethact", "eth2");
58bc0571fcSJoe Hershberger ut_assertok(net_loop(PING));
59*00caae6dSSimon Glass ut_asserteq_str("eth@10002000", env_get("ethact"));
60e58780dcSJoe Hershberger
61382bee57SSimon Glass env_set("ethact", "eth5");
62bc0571fcSJoe Hershberger ut_assertok(net_loop(PING));
63*00caae6dSSimon Glass ut_asserteq_str("eth@10003000", env_get("ethact"));
64e58780dcSJoe Hershberger
65e58780dcSJoe Hershberger return 0;
66e58780dcSJoe Hershberger }
67e58780dcSJoe Hershberger DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
686536b9bbSJoe Hershberger
dm_test_eth_prime(struct unit_test_state * uts)69e721b882SJoe Hershberger static int dm_test_eth_prime(struct unit_test_state *uts)
706536b9bbSJoe Hershberger {
71049a95a7SJoe Hershberger net_ping_ip = string_to_ip("1.1.2.2");
726536b9bbSJoe Hershberger
736536b9bbSJoe Hershberger /* Expected to be "eth@10003000" because of ethprime variable */
74382bee57SSimon Glass env_set("ethact", NULL);
75382bee57SSimon Glass env_set("ethprime", "eth5");
76bc0571fcSJoe Hershberger ut_assertok(net_loop(PING));
77*00caae6dSSimon Glass ut_asserteq_str("eth@10003000", env_get("ethact"));
786536b9bbSJoe Hershberger
796536b9bbSJoe Hershberger /* Expected to be "eth@10002000" because it is first */
80382bee57SSimon Glass env_set("ethact", NULL);
81382bee57SSimon Glass env_set("ethprime", NULL);
82bc0571fcSJoe Hershberger ut_assertok(net_loop(PING));
83*00caae6dSSimon Glass ut_asserteq_str("eth@10002000", env_get("ethact"));
846536b9bbSJoe Hershberger
856536b9bbSJoe Hershberger return 0;
866536b9bbSJoe Hershberger }
876536b9bbSJoe Hershberger DM_TEST(dm_test_eth_prime, DM_TESTF_SCAN_FDT);
887d104eabSJoe Hershberger
896d9764c2SBin Meng /**
906d9764c2SBin Meng * This test case is trying to test the following scenario:
916d9764c2SBin Meng * - All ethernet devices are not probed
926d9764c2SBin Meng * - "ethaddr" for all ethernet devices are not set
936d9764c2SBin Meng * - "ethact" is set to a valid ethernet device name
946d9764c2SBin Meng *
956d9764c2SBin Meng * With Sandbox default test configuration, all ethernet devices are
966d9764c2SBin Meng * probed after power-up, so we have to manually create such scenario:
976d9764c2SBin Meng * - Remove all ethernet devices
986d9764c2SBin Meng * - Remove all "ethaddr" environment variables
996d9764c2SBin Meng * - Set "ethact" to the first ethernet device
1006d9764c2SBin Meng *
1016d9764c2SBin Meng * Do a ping test to see if anything goes wrong.
1026d9764c2SBin Meng */
dm_test_eth_act(struct unit_test_state * uts)1036d9764c2SBin Meng static int dm_test_eth_act(struct unit_test_state *uts)
1046d9764c2SBin Meng {
1056d9764c2SBin Meng struct udevice *dev[DM_TEST_ETH_NUM];
1066d9764c2SBin Meng const char *ethname[DM_TEST_ETH_NUM] = {"eth@10002000", "eth@10003000",
1076d9764c2SBin Meng "sbe5", "eth@10004000"};
1086d9764c2SBin Meng const char *addrname[DM_TEST_ETH_NUM] = {"ethaddr", "eth5addr",
1096d9764c2SBin Meng "eth3addr", "eth1addr"};
1106d9764c2SBin Meng char ethaddr[DM_TEST_ETH_NUM][18];
1116d9764c2SBin Meng int i;
1126d9764c2SBin Meng
1136d9764c2SBin Meng net_ping_ip = string_to_ip("1.1.2.2");
1146d9764c2SBin Meng
1156d9764c2SBin Meng /* Prepare the test scenario */
1166d9764c2SBin Meng for (i = 0; i < DM_TEST_ETH_NUM; i++) {
1176d9764c2SBin Meng ut_assertok(uclass_find_device_by_name(UCLASS_ETH,
1186d9764c2SBin Meng ethname[i], &dev[i]));
119706865afSStefan Roese ut_assertok(device_remove(dev[i], DM_REMOVE_NORMAL));
1206d9764c2SBin Meng
1216d9764c2SBin Meng /* Invalidate MAC address */
122*00caae6dSSimon Glass strcpy(ethaddr[i], env_get(addrname[i]));
1236d9764c2SBin Meng /* Must disable access protection for ethaddr before clearing */
124382bee57SSimon Glass env_set(".flags", addrname[i]);
125382bee57SSimon Glass env_set(addrname[i], NULL);
1266d9764c2SBin Meng }
1276d9764c2SBin Meng
1286d9764c2SBin Meng /* Set ethact to "eth@10002000" */
129382bee57SSimon Glass env_set("ethact", ethname[0]);
1306d9764c2SBin Meng
1316d9764c2SBin Meng /* Segment fault might happen if something is wrong */
1326d9764c2SBin Meng ut_asserteq(-ENODEV, net_loop(PING));
1336d9764c2SBin Meng
1346d9764c2SBin Meng for (i = 0; i < DM_TEST_ETH_NUM; i++) {
1356d9764c2SBin Meng /* Restore the env */
136382bee57SSimon Glass env_set(".flags", addrname[i]);
137382bee57SSimon Glass env_set(addrname[i], ethaddr[i]);
1386d9764c2SBin Meng
1396d9764c2SBin Meng /* Probe the device again */
1406d9764c2SBin Meng ut_assertok(device_probe(dev[i]));
1416d9764c2SBin Meng }
142382bee57SSimon Glass env_set(".flags", NULL);
143382bee57SSimon Glass env_set("ethact", NULL);
1446d9764c2SBin Meng
1456d9764c2SBin Meng return 0;
1466d9764c2SBin Meng }
1476d9764c2SBin Meng DM_TEST(dm_test_eth_act, DM_TESTF_SCAN_FDT);
1486d9764c2SBin Meng
14909129becSJoe Hershberger /* The asserts include a return on fail; cleanup in the caller */
_dm_test_eth_rotate1(struct unit_test_state * uts)15009129becSJoe Hershberger static int _dm_test_eth_rotate1(struct unit_test_state *uts)
1517d104eabSJoe Hershberger {
1527d104eabSJoe Hershberger /* Make sure that the default is to rotate to the next interface */
153382bee57SSimon Glass env_set("ethact", "eth@10004000");
154bc0571fcSJoe Hershberger ut_assertok(net_loop(PING));
155*00caae6dSSimon Glass ut_asserteq_str("eth@10002000", env_get("ethact"));
1567d104eabSJoe Hershberger
1577d104eabSJoe Hershberger /* If ethrotate is no, then we should fail on a bad MAC */
158382bee57SSimon Glass env_set("ethact", "eth@10004000");
159382bee57SSimon Glass env_set("ethrotate", "no");
160bc0571fcSJoe Hershberger ut_asserteq(-EINVAL, net_loop(PING));
161*00caae6dSSimon Glass ut_asserteq_str("eth@10004000", env_get("ethact"));
1627d104eabSJoe Hershberger
16309129becSJoe Hershberger return 0;
16409129becSJoe Hershberger }
16509129becSJoe Hershberger
_dm_test_eth_rotate2(struct unit_test_state * uts)16609129becSJoe Hershberger static int _dm_test_eth_rotate2(struct unit_test_state *uts)
16709129becSJoe Hershberger {
16809129becSJoe Hershberger /* Make sure we can skip invalid devices */
169382bee57SSimon Glass env_set("ethact", "eth@10004000");
17009129becSJoe Hershberger ut_assertok(net_loop(PING));
171*00caae6dSSimon Glass ut_asserteq_str("eth@10004000", env_get("ethact"));
17209129becSJoe Hershberger
17371d7971fSBin Meng /* Make sure we can handle device name which is not eth# */
174382bee57SSimon Glass env_set("ethact", "sbe5");
17571d7971fSBin Meng ut_assertok(net_loop(PING));
176*00caae6dSSimon Glass ut_asserteq_str("sbe5", env_get("ethact"));
17771d7971fSBin Meng
17809129becSJoe Hershberger return 0;
17909129becSJoe Hershberger }
18009129becSJoe Hershberger
dm_test_eth_rotate(struct unit_test_state * uts)18109129becSJoe Hershberger static int dm_test_eth_rotate(struct unit_test_state *uts)
18209129becSJoe Hershberger {
18309129becSJoe Hershberger char ethaddr[18];
18409129becSJoe Hershberger int retval;
18509129becSJoe Hershberger
18609129becSJoe Hershberger /* Set target IP to mock ping */
18709129becSJoe Hershberger net_ping_ip = string_to_ip("1.1.2.2");
18809129becSJoe Hershberger
18909129becSJoe Hershberger /* Invalidate eth1's MAC address */
190*00caae6dSSimon Glass strcpy(ethaddr, env_get("eth1addr"));
19109129becSJoe Hershberger /* Must disable access protection for eth1addr before clearing */
192382bee57SSimon Glass env_set(".flags", "eth1addr");
193382bee57SSimon Glass env_set("eth1addr", NULL);
19409129becSJoe Hershberger
19509129becSJoe Hershberger retval = _dm_test_eth_rotate1(uts);
19609129becSJoe Hershberger
1977d104eabSJoe Hershberger /* Restore the env */
198382bee57SSimon Glass env_set("eth1addr", ethaddr);
199382bee57SSimon Glass env_set("ethrotate", NULL);
2007d104eabSJoe Hershberger
20109129becSJoe Hershberger if (!retval) {
2027d104eabSJoe Hershberger /* Invalidate eth0's MAC address */
203*00caae6dSSimon Glass strcpy(ethaddr, env_get("ethaddr"));
20473c2bbeeSJoe Hershberger /* Must disable access protection for ethaddr before clearing */
205382bee57SSimon Glass env_set(".flags", "ethaddr");
206382bee57SSimon Glass env_set("ethaddr", NULL);
2077d104eabSJoe Hershberger
20809129becSJoe Hershberger retval = _dm_test_eth_rotate2(uts);
2097d104eabSJoe Hershberger
2107d104eabSJoe Hershberger /* Restore the env */
211382bee57SSimon Glass env_set("ethaddr", ethaddr);
21209129becSJoe Hershberger }
21309129becSJoe Hershberger /* Restore the env */
214382bee57SSimon Glass env_set(".flags", NULL);
2157d104eabSJoe Hershberger
21609129becSJoe Hershberger return retval;
2177d104eabSJoe Hershberger }
2187d104eabSJoe Hershberger DM_TEST(dm_test_eth_rotate, DM_TESTF_SCAN_FDT);
2197ece1c61SJoe Hershberger
22009129becSJoe Hershberger /* The asserts include a return on fail; cleanup in the caller */
_dm_test_net_retry(struct unit_test_state * uts)22109129becSJoe Hershberger static int _dm_test_net_retry(struct unit_test_state *uts)
2227ece1c61SJoe Hershberger {
2237ece1c61SJoe Hershberger /*
2247ece1c61SJoe Hershberger * eth1 is disabled and netretry is yes, so the ping should succeed and
2257ece1c61SJoe Hershberger * the active device should be eth0
2267ece1c61SJoe Hershberger */
2277ece1c61SJoe Hershberger sandbox_eth_disable_response(1, true);
228382bee57SSimon Glass env_set("ethact", "eth@10004000");
229382bee57SSimon Glass env_set("netretry", "yes");
230172a31bfSJoe Hershberger sandbox_eth_skip_timeout();
231bc0571fcSJoe Hershberger ut_assertok(net_loop(PING));
232*00caae6dSSimon Glass ut_asserteq_str("eth@10002000", env_get("ethact"));
2337ece1c61SJoe Hershberger
2347ece1c61SJoe Hershberger /*
2357ece1c61SJoe Hershberger * eth1 is disabled and netretry is no, so the ping should fail and the
2367ece1c61SJoe Hershberger * active device should be eth1
2377ece1c61SJoe Hershberger */
238382bee57SSimon Glass env_set("ethact", "eth@10004000");
239382bee57SSimon Glass env_set("netretry", "no");
240172a31bfSJoe Hershberger sandbox_eth_skip_timeout();
241bc0571fcSJoe Hershberger ut_asserteq(-ETIMEDOUT, net_loop(PING));
242*00caae6dSSimon Glass ut_asserteq_str("eth@10004000", env_get("ethact"));
2437ece1c61SJoe Hershberger
24409129becSJoe Hershberger return 0;
24509129becSJoe Hershberger }
24609129becSJoe Hershberger
dm_test_net_retry(struct unit_test_state * uts)24709129becSJoe Hershberger static int dm_test_net_retry(struct unit_test_state *uts)
24809129becSJoe Hershberger {
24909129becSJoe Hershberger int retval;
25009129becSJoe Hershberger
25109129becSJoe Hershberger net_ping_ip = string_to_ip("1.1.2.2");
25209129becSJoe Hershberger
25309129becSJoe Hershberger retval = _dm_test_net_retry(uts);
25409129becSJoe Hershberger
2557ece1c61SJoe Hershberger /* Restore the env */
256382bee57SSimon Glass env_set("netretry", NULL);
2577ece1c61SJoe Hershberger sandbox_eth_disable_response(1, false);
2587ece1c61SJoe Hershberger
25909129becSJoe Hershberger return retval;
2607ece1c61SJoe Hershberger }
2617ece1c61SJoe Hershberger DM_TEST(dm_test_net_retry, DM_TESTF_SCAN_FDT);
262