#17839: Reboot command causes sometimes hanging router with TL-WDR3600 (HW V1.5)
and TL-WDR4300 (HW V1.7)
--------------------------+-----------------------------------
Reporter: michaeluray | Owner: developers
Type: defect | Status: new
Priority: high | Milestone: Barrier Breaker 14.07
Component: base system | Version: Barrier Breaker 14.07
Resolution: | Keywords: reboot
--------------------------+-----------------------------------
Comment (by anonymous):
I have looked at the reboot implementation of the published TP-Link kernel
source code of TL-WDR3600 and compared it with the implemetation in
OpenWRT.
'''TP-Link source code:'''
File TL-WDR3600_GPL_2.6.31.tar.gz: /./GPL_2.6.31/db12x/linux/kernels/mips-
linux-2.6.31/arch/mips/atheros/setup.c
{{{
#!c
void ath_restart(char *command)
{
for (;;) {
if (is_ar934x_10()) {
ath_reg_wr(ATH_GPIO_OE, ath_reg_rd(ATH_GPIO_OE) &
(~(1 << 17)));
} else {
ath_reg_wr(ATH_RESET, ATH_RESET_FULL_CHIP);
}
}
}
}}}
'''OpenWRT trunk source code:'''
openwrt/trunk/build_dir/target-mips_r2_uClibc-0.9.33.2/linux-
ar71xx_generic/linux-3.7.8/arch/mips/ath79/setup.c
{{{
#!c
static void ath79_restart(char *command)
{
ath79_device_reset_set(AR71XX_RESET_FULL_CHIP);
for (;;)
if (cpu_wait)
cpu_wait();
}
}}}
/srv/openwrt/trunk/build_dir/target-mips_r2_uClibc-0.9.33.2/linux-
ar71xx_generic/linux-3.7.8/arch/mips/ath79/common.c
{{{
#!c
void ath79_device_reset_set(u32 mask)
{
unsigned long flags;
u32 reg;
u32 t;
if (soc_is_ar71xx())
reg = AR71XX_RESET_REG_RESET_MODULE;
else if (soc_is_ar724x())
reg = AR724X_RESET_REG_RESET_MODULE;
else if (soc_is_ar913x())
reg = AR913X_RESET_REG_RESET_MODULE;
else if (soc_is_ar933x())
reg = AR933X_RESET_REG_RESET_MODULE;
else if (soc_is_ar934x() ||
soc_is_qca955x())
reg = AR934X_RESET_REG_RESET_MODULE;
else
BUG();
spin_lock_irqsave(&ath79_device_reset_lock, flags);
t = ath79_reset_rr(reg);
ath79_reset_wr(reg, t | mask);
spin_unlock_irqrestore(&ath79_device_reset_lock, flags);
}
}}}
The TP-Link code writes the ATH_RESET_FULL_CHIP value (0x01000000) to the
RESET register in a loop.
The OpenWRT (current kernel?) implementation reads the RESET register (t),
set the bit 24 (t | mask) and write it to the RESET register.
I think in case of an FULL_CHIP reset it is not necessary. I have checked
with "printk" the values of the variables:
{{{
mask = 0x01000000
t = 0x24044008
}}}
I have seen these values at a normal restart and at a brooken restart
(system hangs).
I have also noticed that a "printk" after the line "ath79_reset_wr(reg, t
| mask);" will be not executed in case of an FULL_CHIP reset.
I have tried to change the logic of function "ath79_device_reset_set" by
insert the following code to the function "ath79_device_reset_set" right
before "spin_lock_irqsave" call:
{{{
#!c
if (mask == AR71XX_RESET_FULL_CHIP) {
printk(KERN_WARNING "TEST: ath79_device_reset_set:
RESET_FULL_CHIP\n");
for (;;) {
ath79_reset_wr(reg, mask);
}
}
}}}
I have build an image with this modification based on my (old) current AA
branch and it looks like the problem is gone.
I think this change could not be the final solution because this code will
be used by all Atheros devices and I have no experience in kernel
programming.
But may be this could leads to the right direction.
--
Ticket URL: <https://dev.openwrt.org/ticket/17839#comment:51>
OpenWrt <http://openwrt.org>
Opensource Wireless Router Technology
_______________________________________________
openwrt-tickets mailing list
[email protected]
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-tickets