miiphy: define mii_devs with LIST_HEAD()
authorWeijie Gao <hackpascal@gmail.com>
Sat, 25 Jan 2025 15:26:32 +0000 (23:26 +0800)
committerTom Rini <trini@konsulko.com>
Tue, 4 Mar 2025 14:03:47 +0000 (08:03 -0600)
commit7e0370f37d242f45d2fcfa3ab727d48f88ccace9
tree68ef462c79c2715653ccdc2b39b5f75d5b8eb54d
parente34aa2975abccf135c569e295ef5faf92327268b
miiphy: define mii_devs with LIST_HEAD()

When enabling net console and console multiplexing, a boot crash was
observed using mtk_eth driver with stdin/stdout set to "serial,nc"
in persistent environment:

> CPU:   MediaTek MT7981
> Model: OpenWrt One
> DRAM:  1 GiB
> Core:  35 devices, 15 uclasses, devicetree: separate
> spi-nand: spi_nand spi_nand@0: Winbond SPI NAND was found.
> spi-nand: spi_nand spi_nand@0: 128 MiB, block size: 128 KiB, page size: 2048, OOB size: 64
> Loading Environment from UBI... SF: Detected w25q128 with page size 256 Bytes, erase size 4 KiB, total 16 MiB
> mtd: partition "ubi" extends beyond the end of device "spi-nand0" -- size truncated to 0x7f00000
> Read 126976 bytes from volume ubootenv to 000000007f7bf0c0
> Read 126976 bytes from volume ubootenv2 to 000000007f7de100
> OK
> "Synchronous Abort" handler, esr 0x96000004, far 0xeafffffeea000018
> elr: 0000000041e63cd4 lr : 0000000041e1b844 (reloc)
> elr: 000000007ff9ecd4 lr : 000000007ff56844
> x0 : eafffffeea000018 x1 : 000000007fb552e0
> x2 : 00000000000000fe x3 : 0000000000000000

The cause is that "serial,nc" forced the console subsystem to
initialize the ethernet driver before ethernet subsystem
initialization (console_init_r() is called before initr_net()).

During the mtk_eth driver initialization, mdio_register() will be
called, and miiphy_get_dev_by_name() will then be called.

The miiphy_get_dev_by_name() will check the list "mii_devs" to see
if the passed device name exists. However the mii_devs is defined
without initialization:
> static struct list_head mii_devs;
and the actual initialization is done in the following chain:
initr_net -> eth_initialize -> eth_common_init -> miiphy_init
Since initr_net() hasn't be called, iterating over the mii_devs
will access to physical address 0 (mii_devs.next == NULL) and will
cause the crash.

The fix is to define mii_devs using:
> static LIST_HEAD(mii_devs);

As the "current_mii" is defined as a static variable, it will
always be NULL in board_r stage and initializing it will NULL is
unnecessary. So the entire miiphy_init() can be remove.

Signed-off-by: Weijie Gao <hackpascal@gmail.com>
common/miiphyutil.c
include/miiphy.h
net/eth_common.c