Ubiquiti loco xw eth0 bug: Unterschied zwischen den Versionen
Leo (Diskussion | Beiträge) (init) |
Lars (Diskussion | Beiträge) (Link zum Opennet-Ticket) |
||
(8 dazwischenliegende Versionen von 3 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
− | |||
==Bug description== | ==Bug description== | ||
− | ... | + | Some Ubiquiti loco xw have a hardware bug which results in an interface shutdown with now possibility to bring the interface without reboot. |
+ | More details, see [https://dev.openwrt.org/ticket/19085 OpenWrt #19086] and [https://dev.opennet-initiative.de/ticket/94 Opennet #94]. | ||
+ | |||
+ | This bug is solved since around OpenWrt 18.06.01. | ||
+ | |||
==Steps for building workaround== | ==Steps for building workaround== | ||
===Find a way to detect hang of eth0=== | ===Find a way to detect hang of eth0=== | ||
− | |||
− | + | ====Try 1==== | |
+ | In general there are two places where uid of PHY is printed. | ||
− | + | 1. ag71xx_phy.c | |
− | + | ||
− | + | function: static int ag71xx_phy_connect_multi(struct ag71xx *ag) | |
− | + | .... | |
− | Sun | + | DBG("%s: PHY found at %s, uid=%08x\n", |
− | Sun | + | dev_name(dev), |
+ | dev_name(&ag->mii_bus->phy_map[phy_addr]->dev), | ||
+ | ag->mii_bus->phy_map[phy_addr]->phy_id); | ||
+ | |||
+ | dev_info(dev, "connected to PHY at %s [uid=%08x, driver=%s]\n", | ||
+ | dev_name(&phydev->dev), phydev->phy_id, phydev->drv->name); | ||
+ | |||
+ | 2. ag71xx_main.c | ||
+ | |||
+ | void ag71xx_link_adjust(struct ag71xx *ag) | ||
+ | .... | ||
+ | struct device *dev = &ag->pdev->dev; | ||
+ | struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); | ||
+ | struct phy_device *phydev = NULL; | ||
+ | int phy_addr; | ||
+ | int ret = 0; | ||
+ | |||
+ | for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { | ||
+ | if (!(pdata->phy_mask & (1 << phy_addr))) | ||
+ | continue; | ||
+ | |||
+ | if (ag->mii_bus->phy_map[phy_addr] == NULL) | ||
+ | continue; | ||
+ | |||
+ | DBG("%s: PHY found at %s, uid=%08x\n", | ||
+ | dev_name(dev), | ||
+ | dev_name(&ag->mii_bus->phy_map[phy_addr]->dev), | ||
+ | ag->mii_bus->phy_map[phy_addr]->phy_id); | ||
+ | |||
+ | if (phydev == NULL) | ||
+ | phydev = ag->mii_bus->phy_map[phy_addr]; | ||
+ | } | ||
+ | |||
+ | dev_info(dev, "connected to PHY at %s [uid=%08x, driver=%s]\n", | ||
+ | dev_name(&phydev->dev), phydev->phy_id, phydev->drv->name); | ||
+ | |||
+ | |||
+ | |||
+ | ID can be read in ag71xx_link_adjust() in file ag71xx_main.c. See http://pastebin.com/0ze9iFcb for an example. | ||
+ | '''But''' the ID is not changing when eth0 hangs. The output when it hangs is: | ||
+ | [155921.360000] ag71xx ag71xx.0: connected to PHY at ag71xx-mdio.0:01 [uid=004dd023, driver=Generic PHY] (Opennet-Info1) | ||
+ | [155921.360000] eth0: link up (10Mbps/Half duplex) | ||
+ | [155923.370000] ag71xx ag71xx.0: connected to PHY at ag71xx-mdio.0:01 [uid=004dd023, driver=Generic PHY] (Opennet-Info1) | ||
+ | [155923.370000] eth0: link down | ||
+ | [155923.380000] br-lan: port 1(eth0) entered disabled state | ||
+ | |||
+ | ====Try 2 - mdiobus_read()==== | ||
+ | ...mdiobus_read?? ... read ID was always ffffff which indicated that the bus is in use..... | ||
+ | |||
+ | ====Try 3 - use get_phy_id()==== | ||
+ | |||
+ | in /home/leo/trunk/eth-bug-oni~rivers/net/phy/phy_device.c | ||
+ | + EXPORT_SYMBOL(get_phy_id); | ||
+ | |||
+ | in /home/leo/trunk/eth-bug-oni~3.10.49/include/linux/phy.h | ||
+ | int phy_scan_fixups(struct phy_device *phydev); | ||
+ | |||
+ | + static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id, | ||
+ | + bool is_c45, struct phy_c45_device_ids *c45_ids); | ||
+ | |||
+ | in linux-ar71xx_generic/linux-3.10.49/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c | ||
+ | void ag71xx_link_adjust(struct ag71xx *ag) | ||
+ | { | ||
+ | struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); | ||
+ | + struct mii_bus *mii = ag->mii_bus; | ||
+ | u32 cfg2; | ||
+ | u32 ifctl; | ||
+ | u32 fifo5; | ||
+ | u32 fifo3; | ||
+ | + u32 phy_id; | ||
+ | + int phy_ret; | ||
+ | + bool is_c45 = true; | ||
+ | + struct phy_c45_device_ids c45_ids = {0}; | ||
+ | + | ||
+ | + phy_ret = get_phy_id(mii, 0, &phy_id, is_c45, &c45_ids); | ||
+ | + pr_info("%s: PHY ID is %08x (ret=%d) (unschoener Opennet-Hack v3a)\n", ag->dev->name, phy_id, phy_ret); | ||
+ | + is_c45 = false; | ||
+ | + phy_ret = get_phy_id(mii, 0, &phy_id, is_c45, &c45_ids); | ||
+ | + pr_info("%s: PHY ID is %08x (ret=%d) (unschoener Opennet-Hack v3b)\n", ag->dev->name, phy_id, phy_ret); | ||
+ | |||
+ | Result: | ||
+ | In file included from /home/leo/trunk/eth-bug-oni-trunk/on_firmware/openwrt/build_dir/target-mips_34kc_uClibc-0.9.33.2/linux-ar71xx_generic/linux- 3.10.49/arch/mips/include/asm/mach-ath79/ag71xx_platform.h:17:0, | ||
+ | from arch/mips/ath79/dev-eth.h:15, | ||
+ | from arch/mips/ath79/dev-eth.c:30: | ||
+ | include/linux/phy.h:583:19: error: 'get_phy_id' declared 'static' but never defined [-Werror=unused-function] | ||
+ | static inline int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id, | ||
+ | ^ | ||
+ | cc1: all warnings being treated as errors | ||
+ | |||
+ | '''TODO''': further invest error | ||
+ | |||
+ | ====Try 4 - get_phy_device()==== | ||
+ | --- linux-ar71xx_generic/linux-3.10.49/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c | ||
+ | void ag71xx_link_adjust(struct ag71xx *ag) | ||
+ | { | ||
+ | struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); | ||
+ | + struct mii_bus *mii = ag->mii_bus; | ||
+ | u32 cfg2; | ||
+ | u32 ifctl; | ||
+ | u32 fifo5; | ||
+ | u32 fifo3; | ||
+ | + u32 phy_id; | ||
+ | + bool is_c45 = true; | ||
+ | + struct phy_device *phydev = NULL; | ||
+ | + | ||
+ | + //taken from linux-3.10.49/drivers/of/of_mdio.c | ||
+ | + phydev = get_phy_device(mii, 0, is_c45); | ||
+ | + if (!phydev || IS_ERR(phydev)) { | ||
+ | + pr_info("%s: cannot get PHY at address!! PHY ID is %08x (unschoener Opennet-Hack v3a)\n", ag->dev->name, phy_id); | ||
+ | + } else { | ||
+ | + phy_id = phydev->phy_id; | ||
+ | + pr_info("%s: PHY ID is %08x (unschoener Opennet-Hack v3b)\n", ag->dev->name, phy_id); | ||
+ | + } | ||
+ | + is_c45 = false; | ||
+ | + phydev = get_phy_device(mii, 0, is_c45); | ||
+ | + if (!phydev || IS_ERR(phydev)) { | ||
+ | + pr_info("%s: cannot get PHY at address!! PHY ID is %08x (unschoener Opennet-Hack v3c)\n", ag->dev->name, phy_id); | ||
+ | + } else { | ||
+ | + phy_id = phydev->phy_id; | ||
+ | + pr_info("%s: PHY ID is %08x (unschoener Opennet-Hack v3d)\n", ag->dev->name, phy_id); | ||
+ | + } | ||
+ | |||
+ | |||
+ | Result: | ||
+ | Sun May 10 14:27:29 2015 kern.info kernel: [ 1.150000] ag71xx ag71xx.0: connected to PHY at ag71xx-mdio.0:01 [uid=004dd023, driver=Generic PHY] | ||
+ | Sun May 10 14:27:29 2015 kern.info kernel: [ 6.230000] eth0: cannot get PHY at address!! PHY ID is 00000000 (unschoener Opennet-Hack v3a) | ||
+ | Sun May 10 14:27:29 2015 kern.info kernel: [ 6.230000] eth0: cannot get PHY at address!! PHY ID is 00000000 (unschoener Opennet-Hack v3c) | ||
+ | Sun May 10 14:27:29 2015 kern.info kernel: [ 21.640000] eth0: cannot get PHY at address!! PHY ID is 00000000 (unschoener Opennet-Hack v3a) | ||
+ | Sun May 10 14:27:29 2015 kern.info kernel: [ 21.640000] eth0: cannot get PHY at address!! PHY ID is 00000000 (unschoener Opennet-Hack v3c) | ||
+ | Sun May 10 14:27:35 2015 kern.info kernel: [ 42.380000] eth0: cannot get PHY at address!! PHY ID is 00000000 (unschoener Opennet-Hack v3a) | ||
+ | Sun May 10 14:27:35 2015 kern.info kernel: [ 42.380000] eth0: cannot get PHY at address!! PHY ID is 00000000 (unschoener Opennet-Hack v3c) | ||
+ | |||
+ | '''Idea''': Should we search for the right address and call function with get_phy_device(mii, ''add'', is_c45) instead of get_phy_device(mii, 0, is_c45) ?? | ||
===Find a way to reset eth0=== | ===Find a way to reset eth0=== | ||
− | .. | + | Work in progress: see https://pad.hack-hro.de/p/eth0-bug-loco-xw |
+ | |||
+ | [[Category:Ubiquiti]] | ||
+ | [[Category:Firmware]] |
Aktuelle Version vom 23. März 2019, 16:55 Uhr
Inhaltsverzeichnis |
[Bearbeiten] Bug description
Some Ubiquiti loco xw have a hardware bug which results in an interface shutdown with now possibility to bring the interface without reboot. More details, see OpenWrt #19086 and Opennet #94.
This bug is solved since around OpenWrt 18.06.01.
[Bearbeiten] Steps for building workaround
[Bearbeiten] Find a way to detect hang of eth0
[Bearbeiten] Try 1
In general there are two places where uid of PHY is printed.
1. ag71xx_phy.c
function: static int ag71xx_phy_connect_multi(struct ag71xx *ag) .... DBG("%s: PHY found at %s, uid=%08x\n", dev_name(dev), dev_name(&ag->mii_bus->phy_map[phy_addr]->dev), ag->mii_bus->phy_map[phy_addr]->phy_id); dev_info(dev, "connected to PHY at %s [uid=%08x, driver=%s]\n", dev_name(&phydev->dev), phydev->phy_id, phydev->drv->name);
2. ag71xx_main.c
void ag71xx_link_adjust(struct ag71xx *ag) .... struct device *dev = &ag->pdev->dev; struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); struct phy_device *phydev = NULL; int phy_addr; int ret = 0; for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { if (!(pdata->phy_mask & (1 << phy_addr))) continue; if (ag->mii_bus->phy_map[phy_addr] == NULL) continue; DBG("%s: PHY found at %s, uid=%08x\n", dev_name(dev), dev_name(&ag->mii_bus->phy_map[phy_addr]->dev), ag->mii_bus->phy_map[phy_addr]->phy_id); if (phydev == NULL) phydev = ag->mii_bus->phy_map[phy_addr]; } dev_info(dev, "connected to PHY at %s [uid=%08x, driver=%s]\n", dev_name(&phydev->dev), phydev->phy_id, phydev->drv->name);
ID can be read in ag71xx_link_adjust() in file ag71xx_main.c. See http://pastebin.com/0ze9iFcb for an example. But the ID is not changing when eth0 hangs. The output when it hangs is:
[155921.360000] ag71xx ag71xx.0: connected to PHY at ag71xx-mdio.0:01 [uid=004dd023, driver=Generic PHY] (Opennet-Info1) [155921.360000] eth0: link up (10Mbps/Half duplex) [155923.370000] ag71xx ag71xx.0: connected to PHY at ag71xx-mdio.0:01 [uid=004dd023, driver=Generic PHY] (Opennet-Info1) [155923.370000] eth0: link down [155923.380000] br-lan: port 1(eth0) entered disabled state
[Bearbeiten] Try 2 - mdiobus_read()
...mdiobus_read?? ... read ID was always ffffff which indicated that the bus is in use.....
[Bearbeiten] Try 3 - use get_phy_id()
in /home/leo/trunk/eth-bug-oni~rivers/net/phy/phy_device.c
+ EXPORT_SYMBOL(get_phy_id);
in /home/leo/trunk/eth-bug-oni~3.10.49/include/linux/phy.h
int phy_scan_fixups(struct phy_device *phydev); + static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id, + bool is_c45, struct phy_c45_device_ids *c45_ids);
in linux-ar71xx_generic/linux-3.10.49/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c
void ag71xx_link_adjust(struct ag71xx *ag) { struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); + struct mii_bus *mii = ag->mii_bus; u32 cfg2; u32 ifctl; u32 fifo5; u32 fifo3; + u32 phy_id; + int phy_ret; + bool is_c45 = true; + struct phy_c45_device_ids c45_ids = {0}; + + phy_ret = get_phy_id(mii, 0, &phy_id, is_c45, &c45_ids); + pr_info("%s: PHY ID is %08x (ret=%d) (unschoener Opennet-Hack v3a)\n", ag->dev->name, phy_id, phy_ret); + is_c45 = false; + phy_ret = get_phy_id(mii, 0, &phy_id, is_c45, &c45_ids); + pr_info("%s: PHY ID is %08x (ret=%d) (unschoener Opennet-Hack v3b)\n", ag->dev->name, phy_id, phy_ret);
Result:
In file included from /home/leo/trunk/eth-bug-oni-trunk/on_firmware/openwrt/build_dir/target-mips_34kc_uClibc-0.9.33.2/linux-ar71xx_generic/linux- 3.10.49/arch/mips/include/asm/mach-ath79/ag71xx_platform.h:17:0, from arch/mips/ath79/dev-eth.h:15, from arch/mips/ath79/dev-eth.c:30: include/linux/phy.h:583:19: error: 'get_phy_id' declared 'static' but never defined [-Werror=unused-function] static inline int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id, ^ cc1: all warnings being treated as errors
TODO: further invest error
[Bearbeiten] Try 4 - get_phy_device()
--- linux-ar71xx_generic/linux-3.10.49/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c
void ag71xx_link_adjust(struct ag71xx *ag) { struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); + struct mii_bus *mii = ag->mii_bus; u32 cfg2; u32 ifctl; u32 fifo5; u32 fifo3; + u32 phy_id; + bool is_c45 = true; + struct phy_device *phydev = NULL; + + //taken from linux-3.10.49/drivers/of/of_mdio.c + phydev = get_phy_device(mii, 0, is_c45); + if (!phydev || IS_ERR(phydev)) { + pr_info("%s: cannot get PHY at address!! PHY ID is %08x (unschoener Opennet-Hack v3a)\n", ag->dev->name, phy_id); + } else { + phy_id = phydev->phy_id; + pr_info("%s: PHY ID is %08x (unschoener Opennet-Hack v3b)\n", ag->dev->name, phy_id); + } + is_c45 = false; + phydev = get_phy_device(mii, 0, is_c45); + if (!phydev || IS_ERR(phydev)) { + pr_info("%s: cannot get PHY at address!! PHY ID is %08x (unschoener Opennet-Hack v3c)\n", ag->dev->name, phy_id); + } else { + phy_id = phydev->phy_id; + pr_info("%s: PHY ID is %08x (unschoener Opennet-Hack v3d)\n", ag->dev->name, phy_id); + }
Result:
Sun May 10 14:27:29 2015 kern.info kernel: [ 1.150000] ag71xx ag71xx.0: connected to PHY at ag71xx-mdio.0:01 [uid=004dd023, driver=Generic PHY] Sun May 10 14:27:29 2015 kern.info kernel: [ 6.230000] eth0: cannot get PHY at address!! PHY ID is 00000000 (unschoener Opennet-Hack v3a) Sun May 10 14:27:29 2015 kern.info kernel: [ 6.230000] eth0: cannot get PHY at address!! PHY ID is 00000000 (unschoener Opennet-Hack v3c) Sun May 10 14:27:29 2015 kern.info kernel: [ 21.640000] eth0: cannot get PHY at address!! PHY ID is 00000000 (unschoener Opennet-Hack v3a) Sun May 10 14:27:29 2015 kern.info kernel: [ 21.640000] eth0: cannot get PHY at address!! PHY ID is 00000000 (unschoener Opennet-Hack v3c) Sun May 10 14:27:35 2015 kern.info kernel: [ 42.380000] eth0: cannot get PHY at address!! PHY ID is 00000000 (unschoener Opennet-Hack v3a) Sun May 10 14:27:35 2015 kern.info kernel: [ 42.380000] eth0: cannot get PHY at address!! PHY ID is 00000000 (unschoener Opennet-Hack v3c)
Idea: Should we search for the right address and call function with get_phy_device(mii, add, is_c45) instead of get_phy_device(mii, 0, is_c45) ??
[Bearbeiten] Find a way to reset eth0
Work in progress: see https://pad.hack-hro.de/p/eth0-bug-loco-xw