大家好,最新调试发现,每次启动板子,MAC都不一样,追踪代码发现。内核获取MAC地址通过五种方式(后附上源码)获取mac地址,前面四种获取失败之后,则会通过第五种方式随机生成一个mac地址。我所遇到的情况恰好就是每次启动都是随机生成一个mac地址。
static void fec_get_mac(struct net_device *ndev)
{
struct fec_enet_private *fep = netdev_priv(ndev);
struct fec_platform_data *pdata = dev_get_platdata(&fep->pdev->dev);
unsigned char *iap, tmpaddr[ETH_ALEN];
unsigned char *mem_mac_addr;
/*
* try to get mac address in following order:
*
* 1) module parameter via kernel command line in form
* fec.macaddr=0x00,0x04,0x9f,0x01,0x30,0xe0
*/
iap = macaddr;
/*
* 2) from device tree data
*/
if (!is_valid_ether_addr(iap)) {
struct device_node *np = fep->pdev->dev.of_node;
if (np) {
const char *mac = of_get_mac_address(np);
if (mac)
iap = (unsigned char *) mac;
}
}
/*
* 3) from flash or fuse (via platform data)
*/
if (!is_valid_ether_addr(iap)) {
#ifdef CONFIG_M5272
if (FEC_FLASHMAC)
iap = (unsigned char *)FEC_FLASHMAC;
#else
if (pdata)
iap = (unsigned char *)&pdata->mac;
#endif
}
/*
* 4) FEC mac registers set by bootloader
*/
if (!is_valid_ether_addr(iap)) {
*((__be32 *) &tmpaddr[0]) =
cpu_to_be32(readl(fep->hwp + FEC_ADDR_LOW));
*((__be16 *) &tmpaddr[4]) =
cpu_to_be16(readl(fep->hwp + FEC_ADDR_HIGH) >> 16);
iap = &tmpaddr[0];
}
/*
* 5) random mac address
*/
if (!is_valid_ether_addr(iap)) {
/* Report it and use a random ethernet address instead */
netdev_err(ndev, "Invalid MAC address: %pM\n", iap);
eth_hw_addr_random(ndev);
netdev_info(ndev, "Using random MAC address: %pM\n",
ndev->dev_addr);
return;
}
通过查看IMX6SDLRM.pdf数据手册的“47.5 OCOTP Memory Map/Register Definition”章节,发现MAC地址是已经固化在CPU的MAC里面了,所以我通过操作寄存器的方式获取MAC地址,方法如下:
mem_mac_addr = ioremap(0x021BC620,0x100);
printk("the value is %x\r\n",*(unsigned int *)mem_mac_addr);
ndev->addr_assign_type = NET_ADDR_RANDOM;
*mem_mac_addr &=0xfe;
*mem_mac_addr |= 0x02;
ndev->dev_addr[0] = *mem_mac_addr;
ndev->dev_addr[1] = *(mem_mac_addr+1);
ndev->dev_addr[2] = *(mem_mac_addr+2);
ndev->dev_addr[3] = *(mem_mac_addr+3);
ndev->dev_addr[4] = *(mem_mac_addr+0x12);
*(mem_mac_addr+0x13) &=0xfe;
*(mem_mac_addr+0x13) |= 0x02;
ndev->dev_addr[5] = *(mem_mac_addr+0x13);
return;
修改之后生成的zImage放到不同的板子上跑,结果获取到的MAC都一样:
root@imx6ull14x14evk:~# ifconfig
eth0 Link encap:Ethernet HWaddr 02:00:00:00:00:02
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
我换了一组寄存器地址,分别是: 0x021BC410, 0x021BC420, 0x021BC430,重新编译,放到不同的板子上去跑,结果是每个板子的MAC地址都不一样。
从手册的描述来看, 0x021BC410, 0x021BC420, 0x021BC430 这几个寄存器放的应该是制造商的信息,应该是每个CPU都一样才对。这是什么原因。
疑惑:
1. imx6dl内核的网络驱动有从CPU读取MAC地址的机制吗?(我追踪代码没有找到)
2. 为什么0x021BC620, 0x021BC630 这两个寄存器不能获取到正确的MAC地址?
3. 最终想要解决的问题是:能正确读取CPU的MAC地址,而不是通过软件随机生成一个。
I am not sure what is going wrong in your case.
As a workaround you can add to init script reading MAC address from OCOTP and setting it to the interface.
Have a great day,
Victor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Victor,
Thanks your hlep very much. As I find from OCOTP, there is no MAC address saved in it. I think NXP had not wrote the MAC address to OCOTP. Can you help me to confirm that?? If the MAC address had not wrote into OCOTP, should I get the unique and legal MAC address from NXP?