Kernel Patch for MAC Address in Colibri T30 Mainline

Dear Toradex,

I am currently testing my Mainline uImage for T30 with booting over NFS / TFTP. My setup works so far, however I suffer from the issue that with the mainline kernel, the standard ASIX MAC is used (as explained here Compile Mainline Kernel for Colibry T30 - Toradex Community ).
I would like to change that mac because I test more than one module for the communication between them, otherwise I run into MAC / IP conflicts. The solution provide in the thread above to change the MAC in userspace seems not feasible as my rootfs resides on the NFS share. At least my tries to do so with systemd-networkd (following this MAC address spoofing - ArchWiki ) did not have any effect.

I have seen that for the apalis t30 a kernel patch exists to fix the MAC address issue (discussed here How to compile mainline Linux kernel for Apalis T30? - Toradex Community )
My question is whether there is a similar patch for the colibri T30? Or maybe you see another solution to my dilemma?

Kind regards

The best way to solve this would be to patch the ASIX USB Ethernet driver as follows:

diff --git a/drivers/net/usb/asix.h b/drivers/net/usb/asix.h
index 9a4171b90947..c8161960cef2 100644
--- a/drivers/net/usb/asix.h
+++ b/drivers/net/usb/asix.h
@@ -37,6 +37,7 @@
 #include <linux/usb/usbnet.h>
 #include <linux/slab.h>
 #include <linux/if_vlan.h>
+#include <linux/of_net.h>
 
 #define DRIVER_VERSION "22-Dec-2011"
 #define DRIVER_NAME "asix"
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index 3d4f7959dabb..de88cb8087cc 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -690,25 +690,32 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
        u8 buf[ETH_ALEN], chipcode = 0;
        u32 phyid;
        struct asix_common_private *priv;
+       const u8 *mac_addr;
 
-       usbnet_get_endpoints(dev,intf);
+       usbnet_get_endpoints(dev, intf);
 
-       /* Get the MAC address */
-       if (dev->driver_info->data & FLAG_EEPROM_MAC) {
-               for (i = 0; i < (ETH_ALEN >> 1); i++) {
-                       ret = asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x04 + i,
-                                           0, 2, buf + i * 2, 0);
-                       if (ret < 0)
-                               break;
-               }
+       /* Maybe the boot loader passed the MAC address via device tree */
+       mac_addr = of_get_mac_address(dev->udev->dev.of_node);
+       if (mac_addr) {
+               memcpy(buf, mac_addr, ETH_ALEN);
        } else {
-               ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
-                               0, 0, ETH_ALEN, buf, 0);
-       }
+               /* Try getting the MAC address from EEPROM */
+               if (dev->driver_info->data & FLAG_EEPROM_MAC) {
+                       for (i = 0; i < (ETH_ALEN >> 1); i++) {
+                               ret = asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x04 + i,
+                                                   0, 2, buf + i * 2, 0);
+                               if (ret < 0)
+                                       break;
+                       }
+               } else {
+                       ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
+                                       0, 0, ETH_ALEN, buf, 0);
+               }
 
-       if (ret < 0) {
-               netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret);
-               return ret;
+               if (ret < 0) {
+                       netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret);
+                       return ret;
+               }
        }
 
        asix_set_netdev_dev_addr(dev, buf);

Then combine it with a device tree patch as follows:

diff --git a/arch/arm/boot/dts/tegra30-colibri.dtsi b/arch/arm/boot/dts/tegra30-colibri.dtsi
index c44d8c40c410..1c911a5ed64a 100644
--- a/arch/arm/boot/dts/tegra30-colibri.dtsi
+++ b/arch/arm/boot/dts/tegra30-colibri.dtsi
@@ -439,11 +439,17 @@
        /* EHCI instance 1: USB2_DP/N -> AX88772B */
        usb@7d004000 {
                status = "okay";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               asix@1 {
+                       reg = <1>;
+                       local-mac-address = [00 00 00 00 00 00];
+               };
        };
 
        usb-phy@7d004000 {
                status = "okay";
-               nvidia,is-wired = <1>;
+               vbus-supply = <&lan_vbus_reg>;
        };
 
        clocks {
@@ -503,6 +509,17 @@
                        regulator-max-microvolt = <5000000>;
                        regulator-always-on;
                };
+
+               lan_vbus_reg: regulator@104 {
+                       compatible = "regulator-fixed";
+                       reg = <104>;
+                       regulator-name = "LAN_V_BUS";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(DD, 2) GPIO_ACTIVE_HIGH>;
+                       vin-supply = <&charge_pump_5v0_reg>;
+               };
        };
 
        sound {
@@ -521,3 +538,13 @@
                clock-names = "pll_a", "pll_a_out0", "mclk";
        };
 };
+
+&gpio {
+       lan_reset_n {
+               gpio-hog;
+               gpios = <TEGRA_GPIO(DD, 0) GPIO_ACTIVE_HIGH>;
+               output-high;
+               line-name = "LAN_RESET#";
+       };
+};
+

And have U-Boot fill it all in as follows:

diff --git a/board/toradex/colibri_t30/colibri_t30.c b/board/toradex/colibri_t30/colibri_t30.c
index 8ae3437a49..a93db58124 100644
--- a/board/toradex/colibri_t30/colibri_t30.c
+++ b/board/toradex/colibri_t30/colibri_t30.c
@@ -12,6 +12,7 @@
 #include <asm/gpio.h>
 #include <asm/io.h>
 #include <i2c.h>
+#include <fdt_support.h>
 #include "pinmux-config-colibri_t30.h"
 #include "../common/tdx-common.h"
 
@@ -36,6 +37,17 @@ int checkboard(void)
 #if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
 int ft_board_setup(void *blob, bd_t *bd)
 {
+       uint8_t enetaddr[6];
+
+       fdt_shrink_to_minimum(blob, 0); /* Make room for new properties */
+
+       /* MAC addr */
+       if (eth_getenv_enetaddr("ethaddr", enetaddr)) {
+               fdt_find_and_setprop(blob,
+                                    "/usb@7d004000/asix@1",
+                                    "local-mac-address", enetaddr, 6, 1);
+       }
+
        return ft_common_board_setup(blob, bd);
 }
 #endif

This has been tested with today’s linux-next and our U-Boot 2016.11.

Thank you Mr. Ziswiler. I did copy-paste the first patch into my console where my nano editor was open, removed the first space on every line and I saved it as 01-asix.patch (is there a more elegant way?).
My tries to apply it with patch -p1 < 01-asix.patch failed and the patch was rejected. I tried some kernel versions and for me it seems that it shoud fit to Linus’ Kernel tree ( git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git ). Do you have a clue what I am doing wrong?

I guess AnswerHub’s shitty editor messed it all up! Plus I was missing a tiny little piece on asix.h as well. Try the following patch.

Dear Mr. Ziswiler,

My mileage varies. I did apply the patch now, compile and boot into the patched versions. I still get to see the old MAC when the kernel starts. How can I debug what went wrong?

I also saw that ethaddr in u-boot was set to 00:0e:c6:87:72:01 so I set it manually to some toradex mac which didn’t help either.

kind regards.

U-Boot 2016.11-dirty (Mar 14 2018 - 23:21:32 +0100)

TEGRA30
DRAM:  1 GiB


   Image Name:   Linux-4.16.0-rc5-00004-gfc6eabbb


[    4.872435] asix 2-1:1.0 eth0: register 'asix' at usb-7d004000.usb-1, ASIX AX88772B USB 2.0 Ethernet, **00:0e:c6:87:72:01**

But you did apply the U-Boot patch as well and use the new device tree?

As for the Ethernet MAC address in U-Boot if no ethaddr environment variable is set it will use the one derived from the factory configuration block serial number. Also have a look at the following article on our developer website.

It works now. It seems that something had gone wrong with the u-boot source. Maybe I made a mistake checking out. It’s sometimes very early in the morning, when I have time to work on this.

Thanks for letting us know.

The U-Boot part is now also officially in our downstream version to be released as part of our BSP 2.8b2 later this Q1.

The Linux kernel part I plan to submit for future inclusion in mainline proper.