Kernel does not see mac address set by u-boot

Hi,
We are trying to set the mac address but it seems the kernel does not see it:

Setting in eeprom works fine:

=> tlv_eeprom set 0x24 00:23:45:67:89:AB
=> tlv_eeprom set 0x2A 2
=> tlv_eeprom write
Programming passed.

After boot u-boot seems to see this fine too:

=> tlv_eeprom
TLV: 0
TlvInfo Header:
Id String: TlvInfo
Version: 1
Total Length: 18
TLV Name Code Len Value


Base MAC Address 0x24 6 00:23:45:67:89:AB
MAC Addresses 0x2A 2 2
CRC-32 0xFE 4 0x35506F3A
Checksum is valid.

=> printenv

eth1addr=00:23:45:67:89:AC
ethaddr=00:23:45:67:89:AB

But after booting the kernel we see a different mac address:

# ip a
...
4: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether f2:ba:fe:48:11:74 brd ff:ff:ff:ff:ff:ff
    inet 192.168.68.69/22 metric 1024 brd 192.168.71.255 scope global dynamic eth0
       valid_lft 7190sec preferred_lft 7190sec
    inet6 fe80::f0ba:feff:fe48:1174/64 scope link 
       valid_lft forever preferred_lft forever

Which seems to be random…

What are we missing? How does the kernel read the mac address from u-boot? something isn’t working (we use the latest version of kernel/u-boot built by the runme.sh build script).

Inside u-boot/board/freescale/lx2160a/lx2160a.c I do see this function:

void fdt_fixup_board_enet(void *fdt)
{
	int offset;

	offset = fdt_path_offset(fdt, "/soc/fsl-mc");

	if (offset < 0)
		offset = fdt_path_offset(fdt, "/fsl-mc");

	if (offset < 0) {
		printf("%s: fsl-mc node not found in device tree (error %d)\n",
		       __func__, offset);
		return;
	}

	if (get_mc_boot_status() == 0 &&
	    (is_lazy_dpl_addr_valid() || get_dpl_apply_status() == 0)) {
		fdt_status_okay(fdt, offset);
#ifndef CONFIG_DM_ETH
		fdt_fixup_board_phy(fdt);
#else
		if (IS_ENABLED(CONFIG_TARGET_LX2160ARDB))
			fdt_fixup_board_phy_revc(fdt);
#endif
	} else {
		fdt_status_fail(fdt, offset);
	}
}

We do seem to have CONFIG_DM_ETH defined, so the first fixup isn’t called. We do not seem to have CONFIG_TARGET_LX2160ARDB defined though - we have CONFIG_TARGET_LX2160ACEX7=y - so the 2nd fixup isn’t called as well.

Checking the older SolidRun release we were using so far, I see that it had a slightly different fixup u-boot function, with no #ifdefs:

void fdt_fixup_board_enet(void *fdt)
{
        int offset;

        offset = fdt_path_offset(fdt, "/soc/fsl-mc");

        if (offset < 0)
                offset = fdt_path_offset(fdt, "/fsl-mc");

        if (offset < 0) {
                printf("%s: fsl-mc node not found in device tree (error %d)\n",
                       __func__, offset);
                return;
        }

        if (get_mc_boot_status() == 0 &&
            (is_lazy_dpl_addr_valid() || get_dpl_apply_status() == 0)) {
                fdt_status_okay(fdt, offset);
                fdt_fixup_board_phy(fdt);
        } else {
                fdt_status_fail(fdt, offset);
        }
}

any idea how this should work in the latest SolidRun release and what do we need to further check?

Thanks

The general consensus from the developer working on u-boot for the lx2160a is that the fdt_fixup does matching of MAC → address, so the device-tree is not updated properly with the MAC for the onboard NIC as it is MAC 17 and you only have 2 MACs setup. You can verify this by dumping the device-tree in Linux and verifying this. Short term you can set the number of MACs in the TLV to be 17, but we will work on a patch to refine NXP’s code.

Thanks! Checking this, I have set:

=> tlv_eeprom set 0x24 00:23:45:67:89:00
=> tlv_eeprom set 0x2A 17
=> tlv_eeprom write
Programming passed.
=> tlv_eeprom 
TLV: 0
TlvInfo Header:
   Id String:    TlvInfo
   Version:      1
   Total Length: 18
TLV Name             Code Len Value
-------------------- ---- --- -----
Base MAC Address     0x24   6 00:23:45:67:89:00
MAC Addresses        0x2A   2 17
CRC-32               0xFE   4 0x6E9CF587
Checksum is valid.

U-boot then tells me during boot that:

Net:   eth0: DPMAC3@xgmii, eth1: DPMAC4@xgmii, eth2: DPMAC5@xgmii, eth3: DPMAC6@xgmii, eth4: DPMAC7@xgmii, eth5: DPMAC8@xgmii, eth6: DPMAC9@xgmii, eth7: DPMAC10@xgmii, eth8: DPMAC17@rgmii-id [PRIME]

So it seems dpmac17 gets the 9th entry.

Booting the kernel and checking the address of eth0 validates this:

# ip a show eth0
4: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:23:45:67:89:08 brd ff:ff:ff:ff:ff:ff
    inet 192.168.68.64/22 metric 1024 brd 192.168.71.255 scope global dynamic eth0
       valid_lft 6609sec preferred_lft 6609sec
    inet6 fe80::223:45ff:fe67:8908/64 scope link 
       valid_lft forever preferred_lft forever

But the question is how can I give eth0 a specific address? let’s say I need it to be 00:23:45:67:89:00 and not 00:23:45:67:89:08

There is not way to do this via the existing mechanisms. You could create a custom function for u-boot that specifically patches the rgmii node to use the first MAC address and then start from MAC + 1 for the other interfaces.

ok it’s a bit awkward, but if I want eth0 to have 00:23:45:67:8a:00 then I need to set:

=> tlv_eeprom set 0x24 00:23:45:67:89:F8
=> tlv_eeprom set 0x2A 9

then eth0 will get the 9th entry after F8 which is 00.

hope i’m not missing some other more elegant way.

thanks for the help!

Without patching the existing u-boot code, then yes that is the only way.

1 Like