Hg556a USB 2.0 sometimes stuck at 12mbps

I run OpenWRT 22.03.2 in a Huawei hg556a (B) and noticed that occasionally all three USB ports operate at USB 1.1 speed when they actually are 2.0 and work fine at high speed when they do. Previously I had OpenWRT 21.02 with the same problem.

When this problem shows up it is from the first boot after turn on and persists until power is removed - it survives a hot 'reboot'. I have compared startup logs and they are identical except for the internal USB hub operating with ohci instead of ehci and a notable timing difference in its detection:

Startup with USB 2.0:

[    5.199426] hub 2-0:1.0: USB hub found
[    5.204867] hub 2-0:1.0: 2 ports detected
[    5.216455] kmodloader: done loading kernel modules from /etc/modules-boot.d/*
[    5.235857] init: - preinit -
[    5.633292] usb 1-1: new high-speed USB device number 2 using ehci-platform
[    6.231166] hub 1-1:1.0: USB hub found
[    6.245656] hub 1-1:1.0: 2 ports detected
[    6.414206] random: procd: uninitialized urandom read (4 bytes read)

Startup with USB 1.1:

[    5.210191] hub 2-0:1.0: USB hub found
[    5.217049] hub 2-0:1.0: 2 ports detected
[    5.226551] kmodloader: done loading kernel modules from /etc/modules-boot.d/*
[    5.245128] init: - preinit -
[    6.368954] usb 2-1: new full-speed USB device number 2 using ohci-platform
[    6.787871] usb 2-1: not running at top speed; connect to a high speed hub
[    6.807930] random: procd: uninitialized urandom read (4 bytes read)
[    6.815757] hub 2-1:1.0: USB hub found
[    6.829628] hub 2-1:1.0: 2 ports detected

Note the timing difference in the "new high/full-speed USB" line - only 0,4 in the correct start and 1,1 in the incorrect one. I have two logs and both exhibit this difference.

This problem appears randomly. Yesterday I power cycled the router 6 times and all went in 2.0. Today again and 2 out of 4 boots have been in 1.1. It does not matter whether there is a USB device plugged or not at startup.

Here is the USB configuration with USB 2.0 and nothing plugged:

root@OpenWrt:~# cat /sys/kernel/debug/usb/devices

T:  Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=480  MxCh= 2
B:  Alloc=  0/800 us ( 0%), #Int=  1, #Iso=  0
D:  Ver= 2.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=1d6b ProdID=0002 Rev= 5.10
S:  Manufacturer=Linux 5.10.146 ehci_hcd
S:  Product=EHCI Host Controller
S:  SerialNumber=ehci-platform
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=  0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   4 Ivl=256ms

T:  Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=480  MxCh= 2
D:  Ver= 2.00 Cls=09(hub  ) Sub=00 Prot=01 MxPS=64 #Cfgs=  1
P:  Vendor=0424 ProdID=2502 Rev= 0.01
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=  2mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   1 Ivl=256ms

T:  Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12   MxCh= 2
B:  Alloc=  0/900 us ( 0%), #Int=  0, #Iso=  0
D:  Ver= 1.10 Cls=09(hub  ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=1d6b ProdID=0001 Rev= 5.10
S:  Manufacturer=Linux 5.10.146 ohci_hcd
S:  Product=Generic Platform OHCI controller
S:  SerialNumber=ohci-platform
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=  0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   2 Ivl=255ms

And with USB 1.1:

root@OpenWrt:~# cat /sys/kernel/debug/usb/devices

T:  Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=480  MxCh= 2
B:  Alloc=  0/800 us ( 0%), #Int=  0, #Iso=  0
D:  Ver= 2.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=1d6b ProdID=0002 Rev= 5.10
S:  Manufacturer=Linux 5.10.146 ehci_hcd
S:  Product=EHCI Host Controller
S:  SerialNumber=ehci-platform
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=  0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   4 Ivl=256ms

T:  Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12   MxCh= 2
B:  Alloc=  0/900 us ( 0%), #Int=  1, #Iso=  0
D:  Ver= 1.10 Cls=09(hub  ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=1d6b ProdID=0001 Rev= 5.10
S:  Manufacturer=Linux 5.10.146 ohci_hcd
S:  Product=Generic Platform OHCI controller
S:  SerialNumber=ohci-platform
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=  0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   2 Ivl=255ms

T:  Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 2
D:  Ver= 2.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=0424 ProdID=2502 Rev= 0.01
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=  2mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   1 Ivl=255ms

Driver bug? Workaround possible?

This has probably been this way for some time but I just updated to a Huawei E3372 LTE USB modem from a K4510 3G one and the higher speed made this very obvious. At USB 1.1 speed I get 3-4mbps internet speed while at USB 2.0 I have 10-30mbps.

Thank you!

Hi @j.paul, this seems an old well known usb bug.

It needs kernel patching. Snippet:

	unsigned int * reg = (unsigned int *) 0xfffe150c;

	/* power cycle the USB PLL */
	if (BCMCPU_IS_6358()){
		printk(KERN_INFO PFX "Resetting USB PLL...");
		*reg &= ~0x02000000;
		mdelay(1);
		*reg |= 0x02000000;
		printk("  done\n");
	}

this code should be added to arch/mips/bcm63xx/boards/board_bcm963xx.c

I can compile a firmware to test it if you can't. If the bug is confirmed we can upstream the code.

1 Like

Hi, Thank you!
I recently installed Ubuntu, so will give it a try.

In order to test the fix, would it be possible to perform this reset from a user command, so we know when it starts "wrong" and check if the reset corrects the issue? Otherwise only the time will tell, as it's somewhat random to reproduce.

You may be able to perform this reset using devmem (a firmware with devmem enabled needs to be compiled). But after the reset you should reload the USB drivers.

Hi @danitool

Not sure if I am doing something wrong but can't find the file board_bcm963xx.c in the current git. I find a reference to it here:

https://git.openwrt.org/?p=openwrt/openwrt.git;a=commit;h=c4ab1b7dd9d0194ef8e90847f0fb3e2bf23bfc67

Was it reorganized?
A hint where to add the initialization would help :slight_smile:
Thanks,

The file is under the kernel dir, only available and patched after the first build

build_dir/target-mips_mips32_musl/linux-bcm63xx_smp/linux-5.10.154/arch/mips/bcm63xx/boards/board_bcm963xx.c

Put the code inside the function

void __init board_bcm963xx_init(void)

OK. I checked out v22.03.2 following the Build instructions and built it. Now the file exists and added the code at the end of that function. I was getting these errors:

  CC      arch/mips/bcm63xx/boards/board_bcm963xx.o
arch/mips/bcm63xx/boards/board_bcm963xx.c: In function 'board_bcm963xx_init':
arch/mips/bcm63xx/boards/board_bcm963xx.c:3312:34: error: expected ')' before 'PFX'
 3312 |                 printk(KERN_INFO PFX "Resetting USB PLL...");
      |                       ~          ^~~
arch/mips/bcm63xx/boards/board_bcm963xx.c:3314:17: error: implicit declaration of function 'mdelay' [-Werror=implicit-function-declaration]
 3314 |                 mdelay(1);
      |                 ^~~~~~
cc1: all warnings being treated as errors
scripts/Makefile.build:286: recipe for target 'arch/mips/bcm63xx/boards/board_bcm963xx.o' failed

To fix the first I replaced printk by pr_info as used in this same module and for the second I added #include <linux/delay.h>:

#include <linux/delay.h>

	unsigned int * reg = (unsigned int *) 0xfffe150c;

	/* power cycle the USB PLL */
	if (BCMCPU_IS_6358()){
		pr_info("Resetting USB PLL...");
		*reg &= ~0x02000000;
		mdelay(1);
		*reg |= 0x02000000;
		pr_info("  done\n");
	}

This compiled fine, so I flashed the new bin file with the "flash new firmware" option in LuCi. It flashed and rebooted but I can't find the messages anywhere, not in System log, Kernel log or dmesg.

root@OpenWrt:~# dmesg | grep usb -i
[    4.926939] usbcore: registered new interface driver usbfs
[    4.932754] usbcore: registered new interface driver hub
[    4.938589] usbcore: registered new device driver usb
[    4.971023] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    5.005993] ehci-platform ehci-platform: new USB bus registered, assigned bus number 1
[    5.043715] ehci-platform ehci-platform: USB 2.0 started, EHCI 1.00, overcurrent ignored
[    5.054669] hub 1-0:1.0: USB hub found
[    5.087924] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[    5.112497] ohci-platform ohci-platform: new USB bus registered, assigned bus number 2
[    5.200231] hub 2-0:1.0: USB hub found
[    5.632594] usb 1-1: new high-speed USB device number 2 using ehci-platform
[    6.081968] hub 1-1:1.0: USB hub found

The message should be there, just after the kernel message
board_bcm963xx: Boot address 0x...........

if not, then you are not running the patched firmware

@danitool I found it!
There is a return when it finds a match for the board in the code above. I moved the new code below bcm63xx_nvram_init and now I have the message!
I will test the fix some time and report back.

No way.
I compare the .bin generated before and after the modification and they are different, so apparently it goes in. I flashed the new .bin using the bootloader (press RESET, plug power and hold for 12 seconds) to make sure it is flashed, even added a pr_info out of the if, but no message shows up. I'm out of options.

Maybe related, the directory you refer does not exist but the file is located in this similar one:
./build_dir/target-mips_mips32_musl/linux-bcm63xx_generic/linux-5.10.146/arch/mips/bcm63xx/boards/board_bcm963xx.c

Actually the file exists in these 3 directories:

:~/openwrt$ find . -name board_bcm963xx.c
./staging_dir/target-mips_mips32_musl/bpf-headers/arch/mips/bcm63xx/boards/board_bcm963xx.c
./build_dir/target-mips_mips32_musl/linux-bcm63xx_generic/linux-5.10.146/arch/mips/bcm63xx/boards/board_bcm963xx.c
./build_dir/toolchain-mips_mips32_gcc-11.2.0_musl/linux-5.10.146/arch/mips/bcm63xx/boards/board_bcm963xx.c

Only the second one gets object files generated and is the one I edited. I even saved the original .o file and compared with the new generated after modification and they are different.

Since I can't seem to get it going, can you compile the modification for me?

Cool, let's see if the USB bug is fixed forever.

Hi @danitool
Apparently it works! For now I have not seen slow speeds anymore.
However I suspect 'mdelay(1)' may not be working. as the log does not register any delay and 1ms is a considerable time. Lines 9 and 10:

[    0.000000] Linux version 5.10.146 (builder@buildhost) (mips-openwrt-linux-musl-gcc (OpenWrt GCC 11.2.0 r19803-9a599fee93) 11.2.0, GNU ld (GNU Binutils) 2.37) #0 Fri Oct 14 22:44:41 2022
[    0.000000] Detected Broadcom 0x6358 CPU revision a1
[    0.000000] CPU frequency is 300 MHz
[    0.000000] 64MB of RAM installed
[    0.000000] board_bcm963xx: Boot address 0xbe000000
[    0.000000] board_bcm963xx: CFE version: d081.5003
[    0.000000] bcm63xx_nvram: nvram checksum failed, contents may be invalid (expected 33303639, got 87551c36)
[    0.000000] board_bcm963xx: Extra actions:
[    0.000000] board_bcm963xx: Resetting USB PLL...
[    0.000000] board_bcm963xx:   done
[    0.000000] printk: bootconsole [early0] enabled
[    0.000000] CPU0 revision is: 0002a010 (Broadcom BMIPS4350)
[    0.000000] board: board name: HW556_B
[    0.000000] MIPS: machine is Huawei EchoLife HG556a (version B)
[    0.000000] Initrd not found or empty - disabling initrd
[    0.000000] Primary instruction cache 32kB, VIPT, 2-way, linesize 16 bytes.
[    0.000000] Primary data cache 16kB, 2-way, VIPT, cache aliases, linesize 16 bytes
[    0.000000] Zone ranges:
[    0.000000]   Normal   [mem 0x0000000000000000-0x0000000003ffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000000000000-0x0000000003ffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000000000000-0x0000000003ffffff]
[    0.000000] On node 0 totalpages: 16384
[    0.000000]   Normal zone: 144 pages used for memmap
[    0.000000]   Normal zone: 0 pages reserved
[    0.000000]   Normal zone: 16384 pages, LIFO batch:3
[    0.000000] pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
[    0.000000] pcpu-alloc: [0] 0 
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 16240
[    0.000000] Kernel command line: rootfstype=squashfs,jffs2 noinitrd console=ttyS0,115200
[    0.000000] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes, linear)
[    0.000000] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes, linear)
[    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
[    0.000000] Memory: 56188K/65536K available (5778K kernel code, 634K rwdata, 748K rodata, 1280K init, 205K bss, 9348K reserved, 0K cma-reserved)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] NR_IRQS: 256
[    0.000000] clocksource: MIPS: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 12741736309 ns
[    0.000024] sched_clock: 32 bits at 150MHz, resolution 6ns, wraps every 14316557820ns
[    0.008346] Calibrating delay loop... 299.82 BogoMIPS (lpj=1499136)

And according to some documentation mdelay/udelay use the speed value calculated in the 'Calibrating delay loop' part (last line in the log above). Maybe it can't be used before that?
The fact that it seems to work could be because it does not need such a long reset pulse but still with a too short pulse it could be unreliable.

In fact I was thinking in a better approach. Please use this kernel patch instead:

--- a/arch/mips/bcm63xxk/usb-common.c
+++ b/arch/mips/bcm63xxk/usb-common.c
@@ -15,10 +15,11 @@
 
 #include <bcm63xx_cpu.h>
 #include <bcm63xx_regs.h>
 #include <bcm63xx_io.h>
 #include <bcm63xx_usb_priv.h>
+#include <linux/delay.h>
 
 static DEFINE_SPINLOCK(usb_priv_reg_lock);
 
 void bcm63xx_usb_priv_select_phy_mode(u32 portmask, bool is_device)
 {
@@ -156,10 +157,20 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&usb_priv_reg_lock, flags);
 
 	if (BCMCPU_IS_6358()) {
+		/* power cycle the USB PLL */
+		pr_info("Resetting USB PLL...");
+		reg = bcm_rset_readl(RSET_USBH_PRIV, 0x0c);
+		reg &= ~0x02000000;
+		bcm_rset_writel(RSET_USBH_PRIV, reg, 0x0c);
+		mdelay(1);
+		reg |= 0x02000000;
+		bcm_rset_writel(RSET_USBH_PRIV, reg, 0x0c);
+		printk("  done\n");
+
 		reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6358_REG);
 		reg &= ~USBH_PRIV_SWAP_EHCI_ENDN_MASK;
 		reg |= USBH_PRIV_SWAP_EHCI_DATA_MASK;
 		bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6358_REG);
 

now the code will be at arch/mips/bcm63xxk/usb-common.c, probably a better place.

I'm looking at usb-common.c and mine is different, in bcm63xx_usb_priv_select_phy_mode it does not have the block if (BCMCPU_IS_6358()). I guess the patch is for the current one and not the one in v22.03.2. I also could not find the current usb-common.c, I still don't understand where are located these files that magically appear after the first build.

I can try adding the if and the new code in mine but not sure if that would be right. Also wondering what is that extra code for this CPU in that new version, I hope it is not fixing the problem we are discussing even if a side effect. To be sure I tried to compile the current master branch but make ends with this error:

CMake Error at cmake/StdFilesystem.cmake:22 (message):
  Toolchain doesn't support std::filesystem with nor without -lstdc++fs
Call Stack (most recent call first):
  cmake/StandardSettings.cmake:57 (include)
  CMakeLists.txt:70 (include)

These files are patches under the patch directory of every target, in this case
target/linux/bcm63xx/patches-5.10/

No, if you look at the patch the code is under the line 156 (bcm63xx_usb_priv_ehci_cfg_set)

Thanks, I understand now, it uses patches to create new files.

To apply the patch I edited the path from 'bcm63xxk' (does not exist) to 'bcm63xx', applied, recompiled, flashed and all works as expected, for now it didn't come up at slow speed. So we can close the issue, thank you for your support! @danitool will you apply this patch so it goes in the next release?

The first message uses pr_info and the second printk, so the first shows up as info and the second as warn.

Here is the resulting log:

Thu Dec 15 03:34:38 2022 kern.info kernel: [    4.936243] usbcore: registered new interface driver usbfs
Thu Dec 15 03:34:38 2022 kern.info kernel: [    4.942065] usbcore: registered new interface driver hub
Thu Dec 15 03:34:38 2022 kern.info kernel: [    4.947897] usbcore: registered new device driver usb
Thu Dec 15 03:34:38 2022 kern.info kernel: [    4.979678] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
Thu Dec 15 03:34:38 2022 kern.info kernel: [    4.990557] ehci-fsl: Freescale EHCI Host controller driver
Thu Dec 15 03:34:38 2022 kern.info kernel: [    5.003380] ehci-platform: EHCI generic platform driver
Thu Dec 15 03:34:38 2022 kern.info kernel: [    5.009092] Resetting USB PLL...
Thu Dec 15 03:34:38 2022 kern.warn kernel: [    5.010107]   done
Thu Dec 15 03:34:38 2022 kern.info kernel: [    5.015615] ehci-platform ehci-platform: EHCI Host Controller
Thu Dec 15 03:34:38 2022 kern.info kernel: [    5.021575] ehci-platform ehci-platform: new USB bus registered, assigned bus number 1
Thu Dec 15 03:34:38 2022 kern.info kernel: [    5.030338] ehci-platform ehci-platform: irq 18, io mem 0xfffe1300
Thu Dec 15 03:34:38 2022 kern.info kernel: [    5.063806] ehci-platform ehci-platform: USB 2.0 started, EHCI 1.00, overcurrent ignored
Thu Dec 15 03:34:38 2022 kern.info kernel: [    5.074782] hub 1-0:1.0: USB hub found
Thu Dec 15 03:34:38 2022 kern.info kernel: [    5.081267] hub 1-0:1.0: 2 ports detected
Thu Dec 15 03:34:38 2022 kern.info kernel: [    5.108472] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
Thu Dec 15 03:34:38 2022 kern.info kernel: [    5.120244] ohci-platform: OHCI generic platform driver
Thu Dec 15 03:34:38 2022 kern.info kernel: [    5.126013] ohci-platform ohci-platform: Generic Platform OHCI controller
Thu Dec 15 03:34:38 2022 kern.info kernel: [    5.133091] ohci-platform ohci-platform: new USB bus registered, assigned bus number 2
Thu Dec 15 03:34:38 2022 kern.info kernel: [    5.141696] ohci-platform ohci-platform: irq 13, io mem 0xfffe1400
Thu Dec 15 03:34:38 2022 kern.info kernel: [    5.220347] hub 2-0:1.0: USB hub found
Thu Dec 15 03:34:38 2022 kern.info kernel: [    5.227200] hub 2-0:1.0: 2 ports detected
Thu Dec 15 03:34:38 2022 kern.info kernel: [    5.654150] usb 1-1: new high-speed USB device number 2 using ehci-platform
Thu Dec 15 03:34:38 2022 kern.info kernel: [    6.251756] hub 1-1:1.0: USB hub found
Thu Dec 15 03:34:38 2022 kern.info kernel: [    6.265848] hub 1-1:1.0: 2 ports detected
Thu Dec 15 03:34:38 2022 kern.info kernel: [    6.592097] usb 1-2: new high-speed USB device number 3 using ehci-platform

For some reason flashing the new image through LuCI firmware upgrade preserved the settings but lost all installed modules that I had to reinstall.

Oh sorry it was a custom symlink, it should be bcm63xx. About the prints, they will be deleted for keeping the code as clean as possible. I'll send the patch this week.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.