summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Hershberger <joe.hershberger@ni.com>2015-03-22 17:09:16 -0500
committerSimon Glass <sjg@chromium.org>2015-04-18 11:11:13 -0600
commite58780dcb7b8656ebc2dd6ba6d0da728bc65bf40 (patch)
tree68b6448131caeaa7d02a88cfbb1116e56f3b679b
parentbfacad7da11711231ca59717c0a8bc7317c5bb28 (diff)
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>
-rw-r--r--include/configs/sandbox.h2
-rw-r--r--include/net.h5
-rw-r--r--net/eth.c50
-rw-r--r--test/dm/eth.c24
-rw-r--r--test/dm/test.dts4
5 files changed, 74 insertions, 11 deletions
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index e225ce6772..9769a8dd80 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -178,7 +178,7 @@
#define SANDBOX_ETH_SETTINGS "ethaddr=00:00:11:22:33:44\0" \
"eth1addr=00:00:11:22:33:45\0" \
- "eth2addr=00:00:11:22:33:46\0" \
+ "eth5addr=00:00:11:22:33:46\0" \
"ipaddr=1.2.3.4\0"
#define CONFIG_EXTRA_ENV_SETTINGS SANDBOX_SERIAL_SETTINGS \
diff --git a/include/net.h b/include/net.h
index 0a1b3a827c..942fa4c929 100644
--- a/include/net.h
+++ b/include/net.h
@@ -124,6 +124,11 @@ struct eth_ops {
#define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
struct udevice *eth_get_dev(void); /* get the current device */
+/*
+ * The devname can be either an exact name given by the driver or device tree
+ * or it can be an alias of the form "eth%d"
+ */
+struct udevice *eth_get_dev_by_name(const char *devname);
unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
/* Used only when NetConsole is enabled */
int eth_init_state_only(void); /* Set active state */
diff --git a/net/eth.c b/net/eth.c
index 058c55a0e6..a2e6f34535 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -135,6 +135,39 @@ static void eth_set_dev(struct udevice *dev)
eth_get_uclass_priv()->current = dev;
}
+/*
+ * Find the udevice that either has the name passed in as devname or has an
+ * alias named devname.
+ */
+struct udevice *eth_get_dev_by_name(const char *devname)
+{
+ int seq = -1;
+ char *endp = NULL;
+ const char *startp = NULL;
+ struct udevice *it;
+ struct uclass *uc;
+
+ /* Must be longer than 3 to be an alias */
+ if (strlen(devname) > strlen("eth")) {
+ startp = devname + strlen("eth");
+ seq = simple_strtoul(startp, &endp, 10);
+ }
+
+ uclass_get(UCLASS_ETH, &uc);
+ uclass_foreach_dev(it, uc) {
+ /* We need the seq to be valid, so make sure it's probed */
+ device_probe(it);
+ /*
+ * Check for the name or the sequence number to match
+ */
+ if (strcmp(it->name, devname) == 0 ||
+ (endp > startp && it->seq == seq))
+ return it;
+ }
+
+ return NULL;
+}
+
unsigned char *eth_get_ethaddr(void)
{
struct eth_pdata *pdata;
@@ -421,6 +454,7 @@ UCLASS_DRIVER(eth) = {
.pre_remove = eth_pre_remove,
.priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
.per_device_auto_alloc_size = sizeof(struct eth_device_priv),
+ .flags = DM_UC_FLAG_SEQ_ALIAS,
};
#endif
@@ -453,6 +487,11 @@ static void eth_set_current_to_next(void)
eth_current = eth_current->next;
}
+static void eth_set_dev(struct eth_device *dev)
+{
+ eth_current = dev;
+}
+
struct eth_device *eth_get_dev_by_name(const char *devname)
{
struct eth_device *dev, *target_dev;
@@ -869,7 +908,6 @@ void eth_set_current(void)
{
static char *act;
static int env_changed_id;
- void *old_current;
int env_id;
env_id = get_env_id();
@@ -877,14 +915,8 @@ void eth_set_current(void)
act = getenv("ethact");
env_changed_id = env_id;
}
- if (act != NULL) {
- old_current = eth_get_dev();
- do {
- if (strcmp(eth_get_name(), act) == 0)
- return;
- eth_set_current_to_next();
- } while (old_current != eth_get_dev());
- }
+ if (act != NULL)
+ eth_set_dev(eth_get_dev_by_name(act));
eth_current_changed();
}
diff --git a/test/dm/eth.c b/test/dm/eth.c
index 04ccf49820..5688b71de0 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -36,3 +36,27 @@ static int dm_test_eth(struct dm_test_state *dms)
return 0;
}
DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
+
+static int dm_test_eth_alias(struct dm_test_state *dms)
+{
+ NetPingIP = string_to_ip("1.1.2.2");
+ setenv("ethact", "eth0");
+ ut_assertok(NetLoop(PING));
+ ut_asserteq_str("eth@10002000", getenv("ethact"));
+
+ setenv("ethact", "eth1");
+ ut_assertok(NetLoop(PING));
+ ut_asserteq_str("eth@10004000", getenv("ethact"));
+
+ /* Expected to fail since eth2 is not defined in the device tree */
+ setenv("ethact", "eth2");
+ ut_assertok(NetLoop(PING));
+ ut_asserteq_str("eth@10002000", getenv("ethact"));
+
+ setenv("ethact", "eth5");
+ ut_assertok(NetLoop(PING));
+ ut_asserteq_str("eth@10003000", getenv("ethact"));
+
+ return 0;
+}
+DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
diff --git a/test/dm/test.dts b/test/dm/test.dts
index 762ddc3507..0ab0916858 100644
--- a/test/dm/test.dts
+++ b/test/dm/test.dts
@@ -18,6 +18,8 @@
testfdt3 = "/b-test";
testfdt5 = "/some-bus/c-test@5";
testfdt8 = "/a-test";
+ eth0 = "/eth@10002000";
+ eth5 = &eth_5;
};
uart0: serial {
@@ -172,7 +174,7 @@
fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
};
- eth@10003000 {
+ eth_5: eth@10003000 {
compatible = "sandbox,eth";
reg = <0x10003000 0x1000>;
fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;