[U-Boot] [RFC PATCH v3 11/14] dm: eth: Add support for aliases
Simon Glass
sjg at chromium.org
Wed Feb 18 06:02:21 CET 2015
Hi Joe,
On 16 February 2015 at 22:04, Joe Hershberger <joe.hershberger at gmail.com> wrote:
>
>
> On Sun, Feb 15, 2015 at 9:50 AM, Simon Glass <sjg at chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger at ni.com>
>> wrote:
>> > Allow network devices to be referred to as "eth0" instead of
>> > "eth at 12345678" when specified in ethact.
>> >
>> > Add tests to verify this behavior.
>> >
>> > Signed-off-by: Joe Hershberger <joe.hershberger at ni.com>
>> >
>> > ---
>> >
>> > Changes in v3:
>> > -Added support for aliases
>> >
>> > Changes in v2: None
>> >
>> > include/configs/sandbox.h | 4 ++--
>> > include/fdtdec.h | 1 +
>> > include/net.h | 5 +++++
>> > lib/fdtdec.c | 1 +
>> > net/eth.c | 53
>> > +++++++++++++++++++++++++++++++++++++++--------
>> > test/dm/eth.c | 25 ++++++++++++++++++++++
>> > test/dm/test.dts | 10 +++++----
>> > 7 files changed, 84 insertions(+), 15 deletions(-)
>> >
>> > diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
>> > index fdba1c8..9df5f74 100644
>> > --- a/include/configs/sandbox.h
>> > +++ b/include/configs/sandbox.h
>> > @@ -187,7 +187,7 @@
>> > "stderr=serial,lcd\0" \
>> > "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"
>> > #else
>> >
>> > @@ -196,7 +196,7 @@
>> > "stderr=serial,lcd\0" \
>> > "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"
>> > #endif
>> >
>> > diff --git a/include/fdtdec.h b/include/fdtdec.h
>> > index 231eed7..e945baa 100644
>> > --- a/include/fdtdec.h
>> > +++ b/include/fdtdec.h
>> > @@ -167,6 +167,7 @@ enum fdt_compat_id {
>> > COMPAT_INTEL_GMA, /* Intel Graphics Media
>> > Accelerator */
>> > COMPAT_AMS_AS3722, /* AMS AS3722 PMIC */
>> > COMPAT_INTEL_ICH_SPI, /* Intel ICH7/9 SPI controller
>> > */
>> > + COMPAT_ETHERNET, /* Ethernet devices */
>>
>> SANDBOX_ETHERNET
>
> This is not limited to sandbox. This is needed for all Ethernet MACs. Is
> there some other way that I should be identifying with all devices in the
> device tree of a certain class?
Not that I know of. But each Ethernet driver would need its own
compatible string, since otherwise driver model won't use the right
driver.
>
>> >
>> > COMPAT_COUNT,
>> > };
>> > diff --git a/include/net.h b/include/net.h
>> > index 11471bd..4e98850 100644
>> > --- a/include/net.h
>> > +++ b/include/net.h
>> > @@ -38,6 +38,8 @@
>> >
>> > #define PKTALIGN ARCH_DMA_MINALIGN
>> >
>> > +#define ETH_MAX_DEVS 32
>> > +
>> > /* IPv4 addresses are always 32 bits in size */
>> > typedef __be32 IPaddr_t;
>> >
>> > @@ -79,6 +81,8 @@ enum eth_state_t {
>> > };
>> >
>> > #ifdef CONFIG_DM_ETH
>> > +#define ETH_ALIAS_ROOT "eth"
>> > +
>> > struct eth_pdata {
>> > phys_addr_t iobase;
>> > unsigned char enetaddr[6];
>> > @@ -96,6 +100,7 @@ struct eth_ops {
>> > };
>> >
>> > struct udevice *eth_get_dev(void); /* get the current device */
>> > +struct udevice *eth_get_dev_by_name(const char *devname);
>> > unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
>> > int eth_init_state_only(bd_t *bis); /* Set active state */
>> > void eth_halt_state_only(void); /* Set passive state */
>> > diff --git a/lib/fdtdec.c b/lib/fdtdec.c
>> > index 5bf8f29..33b0a53 100644
>> > --- a/lib/fdtdec.c
>> > +++ b/lib/fdtdec.c
>> > @@ -75,6 +75,7 @@ static const char * const compat_names[COMPAT_COUNT] =
>> > {
>> > COMPAT(INTEL_GMA, "intel,gma"),
>> > COMPAT(AMS_AS3722, "ams,as3722"),
>> > COMPAT(INTEL_ICH_SPI, "intel,ich-spi"),
>> > + COMPAT(ETHERNET, "eth"),
>>
>> sandbox,eth
>
> Again, this is used to identify all Ethernet controllers. Perhaps
> fdtdec_find_aliases_for_id() should not be limiting the alias search to
> those that have a certain "compatible" string?
I think you want 'sandbox,ethernet' here, or similar, but you probably
don't want to use that fdtdec function ultimately. Driver model should
do it all for you.
>
>
>> > };
>> >
>> > const char *fdtdec_get_compatible(enum fdt_compat_id id)
>> > diff --git a/net/eth.c b/net/eth.c
>> > index e84b948..762effe 100644
>> > --- a/net/eth.c
>> > +++ b/net/eth.c
>> > @@ -10,11 +10,14 @@
>> > #include <command.h>
>> > #include <dm.h>
>> > #include <dm/device-internal.h>
>> > +#include <fdtdec.h>
>> > #include <net.h>
>> > #include <miiphy.h>
>> > #include <phy.h>
>> > #include <asm/errno.h>
>> >
>> > +DECLARE_GLOBAL_DATA_PTR;
>> > +
>> > void eth_parse_enetaddr(const char *addr, uchar *enetaddr)
>> > {
>> > char *end;
>> > @@ -121,6 +124,39 @@ static void eth_set_dev(struct udevice *dev)
>> > uc_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 node_list[ETH_MAX_DEVS];
>> > + int count;
>> > + int seq;
>> > + char *endp = NULL;
>> > + const char *true_name = devname;
>> > + struct udevice *it;
>> > + struct uclass *uc;
>> > +
>> > + count = fdtdec_find_aliases_for_id(gd->fdt_blob, ETH_ALIAS_ROOT,
>> > + COMPAT_ETHERNET, node_list,
>> > + ETH_MAX_DEVS);
>> > +
>> > + seq = simple_strtoul(devname + strlen(ETH_ALIAS_ROOT), &endp,
>> > 10);
>> > +
>> > + if (endp > devname + strlen(ETH_ALIAS_ROOT) && count > seq &&
>> > + node_list[seq])
>> > + true_name = fdt_get_name(gd->fdt_blob, node_list[seq],
>> > NULL);
>> > +
>> > + uclass_get(UCLASS_ETH, &uc);
>> > + uclass_foreach_dev(it, uc) {
>> > + if (strcmp(it->name, true_name) == 0 || it->seq == seq)
>> > + return it;
>> > + }
>>
>> Is it possible for eth_get_dev_by_name() to just look up the name
>> provided?
>>
>> You already have this:
>>
>> uclass_foreach_dev(it, uc) {
>> if (strcmp(it->name, true_name) == 0 || it->seq == seq)
>> return it;
>> }
>>
>> It feels like you just need to through through the devices in the
>> uclass and strcmp(dev->name, find_name).
>
> That works fine for looking up the exact name, but that's not the point of
> this patch. Such code was already there and you can see it below.
OK
>
>> I guess I am suffering because I don't understand what you are trying
>> to do, so am not sure if there is an easier way with driver model. We
>> really should not go looking in the device tree in
>> eth_get_dev_by_name()...driver is responsible for parsing that.
>
> Perhaps this is a limitation of fdtdec_find_aliases_for_id(). I need to be
> able to look up the device based on its alias. It doesn't seem to me that
> I'm digging around in the device tree at random places that should be done
> by the driver. I'm simply wanting to ask the device tree what the alias
> that the user passed in is pointing at. Potentially is it not an alias, but
> a full name. Either way, I want to return the udevice.
If you want to know the device's number, use dev->req_seq. This will
hold the alias number. If it is -1 then the device is not mentioned in
/aliases in the device tree.
But please see if you can use the existing driver model features to
find devices, their numbers, etc.
>
>
>> > +
>> > + return NULL;
>> > +}
>> > +
>> > unsigned char *eth_get_ethaddr(void)
>> > {
>> > struct eth_pdata *pdata;
>> > @@ -396,6 +432,7 @@ UCLASS_DRIVER(eth) = {
>> > .init = eth_uclass_init,
>> > .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
>> >
>> > @@ -428,6 +465,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;
>> > @@ -844,7 +886,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();
>> > @@ -852,14 +893,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());
>> > - }
>
> This is the simple compare that is being replaced.
>
>> > + 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 2b29fa2..c0a8ab5 100644
>> > --- a/test/dm/eth.c
>> > +++ b/test/dm/eth.c
>> > @@ -37,3 +37,28 @@ static int dm_test_eth(struct dm_test_state *dms)
>> > }
>> >
>> > 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 at 10002000", getenv("ethact"));
>> > +
>> > + setenv("ethact", "eth1");
>> > + ut_assertok(NetLoop(PING));
>> > + ut_asserteq_str("eth at 10004000", getenv("ethact"));
>> > +
>> > + /* Expected to fail since eth2 is not defined in the device tree
>> > */
>> > + setenv("ethact", "eth2");
>> > + ut_asserteq(-1, NetLoop(PING));
>> > + ut_asserteq_ptr(NULL, getenv("ethact"));
>> > +
>> > + setenv("ethact", "eth5");
>> > + ut_assertok(NetLoop(PING));
>> > + ut_asserteq_str("eth at 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 2f68cdf..c5008c3 100644
>> > --- a/test/dm/test.dts
>> > +++ b/test/dm/test.dts
>> > @@ -17,6 +17,8 @@
>> > testfdt3 = "/b-test";
>> > testfdt5 = "/some-bus/c-test at 5";
>> > testfdt8 = "/a-test";
>> > + eth0 = "/eth at 10002000";
>> > + eth5 = ð_5;
>> > };
>> >
>> > uart0: serial {
>> > @@ -150,19 +152,19 @@
>> > };
>> >
>> > eth at 10002000 {
>> > - compatible = "sandbox,eth";
>> > + compatible = "sandbox,eth", "eth";
>> > reg = <0x10002000 0x1000>;
>> > fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
>> > };
>> >
>> > - eth at 10003000 {
>> > - compatible = "sandbox,eth";
>> > + eth_5: eth at 10003000 {
>> > + compatible = "sandbox,eth", "eth";
>> > reg = <0x10003000 0x1000>;
>> > fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
>> > };
>> >
>> > eth at 10004000 {
>> > - compatible = "sandbox,eth";
>> > + compatible = "sandbox,eth", "eth";
>> > reg = <0x10004000 0x1000>;
>> > fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x22>;
>> > };
>> > --
>> > 1.7.11.5
Regards,
Simon
More information about the U-Boot
mailing list