Commit e58780dcb7b8656ebc2dd6ba6d0da728bc65bf40
Committed by
Simon Glass
1 parent
bfacad7da1
Exists in
v2017.01-smarct4x
and in
34 other branches
dm: eth: Add support for aliases
Allow network devices to be referred to as "eth0" instead of "eth@12345678" when specified in ethact. Add tests to verify this behavior. Signed-off-by: Joe Hershberger <joe.hershberger@ni.com> Reviewed-by: Simon Glass <sjg@chromium.org>
Showing 5 changed files with 74 additions and 11 deletions Side-by-side Diff
include/configs/sandbox.h
... | ... | @@ -178,7 +178,7 @@ |
178 | 178 | |
179 | 179 | #define SANDBOX_ETH_SETTINGS "ethaddr=00:00:11:22:33:44\0" \ |
180 | 180 | "eth1addr=00:00:11:22:33:45\0" \ |
181 | - "eth2addr=00:00:11:22:33:46addr=00:00:11:22:33:46\0" \" \ | |
181 | + "eth5addr=00:00:11:22:33:46addr=00:00:11:22:33:46\0" \" \ | |
182 | 182 | "ipaddr=1.2.3.4\0" |
183 | 183 | |
184 | 184 | #define CONFIG_EXTRA_ENV_SETTINGS SANDBOX_SERIAL_SETTINGS \ |
include/net.h
... | ... | @@ -124,6 +124,11 @@ |
124 | 124 | #define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops) |
125 | 125 | |
126 | 126 | struct udevice *eth_get_dev(void); /* get the current device */ |
127 | +/* | |
128 | + * The devname can be either an exact name given by the driver or device tree | |
129 | + * or it can be an alias of the form "eth%d" | |
130 | + */ | |
131 | +struct udevice *eth_get_dev_by_name(const char *devname); | |
127 | 132 | unsigned char *eth_get_ethaddr(void); /* get the current device MAC */ |
128 | 133 | /* Used only when NetConsole is enabled */ |
129 | 134 | int eth_init_state_only(void); /* Set active state */ |
net/eth.c
... | ... | @@ -135,6 +135,39 @@ |
135 | 135 | eth_get_uclass_priv()->current = dev; |
136 | 136 | } |
137 | 137 | |
138 | +/* | |
139 | + * Find the udevice that either has the name passed in as devname or has an | |
140 | + * alias named devname. | |
141 | + */ | |
142 | +struct udevice *eth_get_dev_by_name(const char *devname) | |
143 | +{ | |
144 | + int seq = -1; | |
145 | + char *endp = NULL; | |
146 | + const char *startp = NULL; | |
147 | + struct udevice *it; | |
148 | + struct uclass *uc; | |
149 | + | |
150 | + /* Must be longer than 3 to be an alias */ | |
151 | + if (strlen(devname) > strlen("eth")) { | |
152 | + startp = devname + strlen("eth"); | |
153 | + seq = simple_strtoul(startp, &endp, 10); | |
154 | + } | |
155 | + | |
156 | + uclass_get(UCLASS_ETH, &uc); | |
157 | + uclass_foreach_dev(it, uc) { | |
158 | + /* We need the seq to be valid, so make sure it's probed */ | |
159 | + device_probe(it); | |
160 | + /* | |
161 | + * Check for the name or the sequence number to match | |
162 | + */ | |
163 | + if (strcmp(it->name, devname) == 0 || | |
164 | + (endp > startp && it->seq == seq)) | |
165 | + return it; | |
166 | + } | |
167 | + | |
168 | + return NULL; | |
169 | +} | |
170 | + | |
138 | 171 | unsigned char *eth_get_ethaddr(void) |
139 | 172 | { |
140 | 173 | struct eth_pdata *pdata; |
... | ... | @@ -421,6 +454,7 @@ |
421 | 454 | .pre_remove = eth_pre_remove, |
422 | 455 | .priv_auto_alloc_size = sizeof(struct eth_uclass_priv), |
423 | 456 | .per_device_auto_alloc_size = sizeof(struct eth_device_priv), |
457 | + .flags = DM_UC_FLAG_SEQ_ALIAS, | |
424 | 458 | }; |
425 | 459 | #endif |
426 | 460 | |
... | ... | @@ -453,6 +487,11 @@ |
453 | 487 | eth_current = eth_current->next; |
454 | 488 | } |
455 | 489 | |
490 | +static void eth_set_dev(struct eth_device *dev) | |
491 | +{ | |
492 | + eth_current = dev; | |
493 | +} | |
494 | + | |
456 | 495 | struct eth_device *eth_get_dev_by_name(const char *devname) |
457 | 496 | { |
458 | 497 | struct eth_device *dev, *target_dev; |
... | ... | @@ -869,7 +908,6 @@ |
869 | 908 | { |
870 | 909 | static char *act; |
871 | 910 | static int env_changed_id; |
872 | - void *old_current; | |
873 | 911 | int env_id; |
874 | 912 | |
875 | 913 | env_id = get_env_id(); |
... | ... | @@ -877,14 +915,8 @@ |
877 | 915 | act = getenv("ethact"); |
878 | 916 | env_changed_id = env_id; |
879 | 917 | } |
880 | - if (act != NULL) { | |
881 | - old_current = eth_get_dev(); | |
882 | - do { | |
883 | - if (strcmp(eth_get_name(), act) == 0) | |
884 | - return; | |
885 | - eth_set_current_to_next(); | |
886 | - } while (old_current != eth_get_dev()); | |
887 | - } | |
918 | + if (act != NULL) | |
919 | + eth_set_dev(eth_get_dev_by_name(act)); | |
888 | 920 | |
889 | 921 | eth_current_changed(); |
890 | 922 | } |
test/dm/eth.c
... | ... | @@ -36,4 +36,28 @@ |
36 | 36 | return 0; |
37 | 37 | } |
38 | 38 | DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT); |
39 | + | |
40 | +static int dm_test_eth_alias(struct dm_test_state *dms) | |
41 | +{ | |
42 | + NetPingIP = string_to_ip("1.1.2.2"); | |
43 | + setenv("ethact", "eth0"); | |
44 | + ut_assertok(NetLoop(PING)); | |
45 | + ut_asserteq_str("eth@10002000", getenv("ethact")); | |
46 | + | |
47 | + setenv("ethact", "eth1"); | |
48 | + ut_assertok(NetLoop(PING)); | |
49 | + ut_asserteq_str("eth@10004000", getenv("ethact")); | |
50 | + | |
51 | + /* Expected to fail since eth2 is not defined in the device tree */ | |
52 | + setenv("ethact", "eth2"); | |
53 | + ut_assertok(NetLoop(PING)); | |
54 | + ut_asserteq_str("eth@10002000", getenv("ethact")); | |
55 | + | |
56 | + setenv("ethact", "eth5"); | |
57 | + ut_assertok(NetLoop(PING)); | |
58 | + ut_asserteq_str("eth@10003000", getenv("ethact")); | |
59 | + | |
60 | + return 0; | |
61 | +} | |
62 | +DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT); |
test/dm/test.dts
... | ... | @@ -18,6 +18,8 @@ |
18 | 18 | testfdt3 = "/b-test"; |
19 | 19 | testfdt5 = "/some-bus/c-test@5"; |
20 | 20 | testfdt8 = "/a-test"; |
21 | + eth0 = "/eth@10002000"; | |
22 | + eth5 = ð_5; | |
21 | 23 | }; |
22 | 24 | |
23 | 25 | uart0: serial { |
... | ... | @@ -172,7 +174,7 @@ |
172 | 174 | fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>; |
173 | 175 | }; |
174 | 176 | |
175 | - eth@10003000 { | |
177 | + eth_5: eth@10003000 { | |
176 | 178 | compatible = "sandbox,eth"; |
177 | 179 | reg = <0x10003000 0x1000>; |
178 | 180 | fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>; |