rt2570 on TiVo Series 2 NEC R5432 MIPS big-endian

Live forum: http://rt2x00.serialmonkey.com/viewtopic.php?t=5057


27-10-2008 17:46:11

I'm in the process of trying to get the rt2570 driver working on a Tivo Series 2 Stand-Alone unit which is a NEC R5432 MIPS running Linux 2.4.20.

Starting with the latest CVS as of yesterday, I hacked a few things in order to get the driver to compile and recognize the device. However, after the few adjustments, once I ifconfig the rausb0 interface, the TiVo starts spewing lines like this non-stop

[code1k6gqy43]Unaligned Access to 0x80d43076 in kernel mode at 0xc021cd8c
Unaligned Access to 0x802d704a in kernel mode at 0xc021b3dc
Unaligned Access to 0x802d704a in kernel mode at 0xc021b408
Unaligned Access to 0x802d704a in kernel mode at 0xc021dc2c[/code1k6gqy43]

There's a bunch of different addresses that show up as it scrolls by.

I made this change to rt_config.h --

[code1k6gqy43]#if defined(__BIG_ENDIAN) || defined(__BIG_ENDIAN__) || \
defined(_BIG_ENDIAN) || defined(__ARMEB__) || defined(__MIPSEB__)[/code1k6gqy43]

(added the "|| defined(__MIPSEB__)" to the end)

I made this change to rtusb_main.c --

[code1k6gqy43] for (i = 0; i < rtusb_usb_id_len; i++)
#ifdef __MIPSEB__
if (dev->descriptor.idVendor == rtusb_usb_id[i].idVendor &&
dev->descriptor.idProduct == rtusb_usb_id[i].idProduct)
if (le16_to_cpu(dev->descriptor.idVendor) == rtusb_usb_id[i].idVendor &&
le16_to_cpu(dev->descriptor.idProduct) == rtusb_usb_id[i].idProduct)

Without that change, it wouldn't detect the device (always saying "Device Descriptor not matching").

Any chance there's still interest in working on this driver to get it working on big-endian MIPS? I'm sure there will be many happy TiVo owners who would love to see this work done.


27-10-2008 17:52:55

So, I built the rt2570 with symbols, and was able to track one of the unaligned accesses back to sanity.cPeerBeaconAndProbeRspSanity(). Specifically

[code37a08ksb] 498 // get timestamp from payload and advance the pointer
499 memcpy(Timestamp, Ptr, TIMESTAMP_LEN);
502 // get beacon interval from payload and advance the pointer
503 *BeaconPeriod = le16_to_cpup((PUSHORT)(Ptr));
504 Ptr += 2;[/code37a08ksb]

The assembly for this

2b810: 8fa20078 lw v0,120(sp)
2b814: 8ac40018 lwl a0,24(s6)
2b818: 9ac4001b lwr a0,27(s6)
2b81c: 8ac5001c lwl a1,28(s6)
2b820: 9ac5001f lwr a1,31(s6)
2b824: a8440000 swl a0,0(v0)
2b828: b8440003 swr a0,3(v0)
2b82c: a8450004 swl a1,4(v0)
2b830: b8450007 swr a1,7(v0)
2b834: 96c20020 lhu v0,32(s6)
2b838: 304300ff andi v1,v0,0xff
2b83c: 00031a00 sll v1,v1,0x8
2b840: 00021202 srl v0,v0,0x8
2b844: 00621825 or v1,v1,v0
2b848: 8fa20070 lw v0,112(sp)
2b84c: a4430000 sh v1,0(v0)[/code37a08ksb]

Specifically, the trap happens at 2b834

[code37a08ksb] 2b834: 96c20020 lhu v0,32(s6)[/code37a08ksb]

Here's the relevant lines from swab.h

[code37a08ksb] 163 static __inline__ __u16 __swab16p(__u16 *x)
164 {
165 return __arch__swab16p(x);
166 }[/code37a08ksb]

I'm going to keep digging, but maybe this will make a lot of sense to Vern or someone else as to why this is resulting in an Unaligned Access trap.


27-10-2008 18:21:36

Getting some help from folks in #tivohelp on freenode IRC, I added a simple printk() to sanity.c to check to see if either of the pointers are halfword aligned, and I got this

[code12dj9jb3]rt2570: <-- RTUSBBulkReceive: PendingRx=8 of 8, NextRxIndex=2
rt2570: BeaconPeriod = 0x80539e68, Ptr = 0x80210d39
Unaligned Access to 0x80210d39 in kernel mode at 0xc0217904
Unaligned Access to 0x80210d3b in kernel mode at 0xc021791c
rt2570: - PeerBeaconAndProbeRspSanity - unrecognized EID = 47 Len = 1: 04[/code12dj9jb3]

Yup, [b12dj9jb3]Ptr[/b12dj9jb3] isn't halfword aligned. Ugh. -)


27-10-2008 20:57:44

Here's another place in the code where an alignment issue popped up

[code2xp0e251] 1713 pRxD = (PRXD_STRUC)(pData + pRxContext->pUrb->actual_length - sizeof(RXD_STRUC));
1714 flipRxDescriptor(pRxD);[/code2xp0e251]

That flipRxDescriptor() is interesting

[code2xp0e251] 514 static inline void flipRxDescriptor(
516 {
517 le32_to_cpus((u32 *)(pRxD));
519 } /* End flipRxDescriptor () */[/code2xp0e251]

What's the right solution, here? I'd hate to double-copy buffers just to align them for this platform, but these byteorder swapping macros need to be used on properly aligned addresses.

Help? Somebody? Anybody? -)

This seems like a systematic problem ...


27-10-2008 21:12:41

Also, loading the driver results in a kernel panic after 10-15 seconds. Here's some of the kernel log leading up to it, then the panic

[codehnuycqqb]Unaligned Access to 0x813c7076 in kernel mode at 0xc021d978
Unaligned Access to 0x813c7076 in kernel mode at 0xc021d74c
Unaligned Access to 0x813c7076 in kernel mode at 0xc021b568
Oops in /build/sandbox-b-7-2-2-mr-release-mips-other/b-7-2-2-mr/os/linux-2.4/arc
h/mips/mm/fault.c::do_page_fault, line 395:
$0 : 00000000 9001fc00 ffffffff 4f505152 4f505152 fffffffe 8052cdb3 8052cd94
$8 : ffffffff 0000000a 00000000 8052cdc8 00000000 00000000 fffffffb ffffffff
$16: 801609c7 80160db7 00000019 8052cd98 4f505152 ffffffff 801609b8 00000400
$24: 0000000a 00000000 8052c000 8052cd10 00000002 8012cddc
Hi : 00000833
Lo : 33333a60
epc : 8012bf44 Tainted: P
Status: 9001fc02
Cause : 00000008
Process rausb0-Cmd (pid: 361, stackpage=8052c000)
Stack: 4748494a 4b4c4d4e 4f505152 53545556 5758595a 0000003c 8052cdc7
8052ce3f 00000000 9001fc01 0000000b 0000000b 00000002 00000000 0000000a
00000000 80020844 c01ec0c0 0000000a ffffffff 8052cdb3 00000002 00000000
80220160 00000000 80220160 0000000b 0000000b 00000002 00000000 0000000a
c01ec0c0 4c6f7720 4f505152 c021edb7 53545556 5174795b 35345d3d 30205045
523d3025 ...

Trace: 8012bf44 8012cddc 80020844 c01ec0c0 c01f0bc0 c01efad8 c01ec868 (Bad trace
Code: 2402ffff 10a2000b 00801821 <80820000> 10400008 00000000 2406ffff 24a5
ffff 10a60004
rt2570: --->RTUSBBulkRxComplete status=0 len=134 PendingRx=7
rt2570: --->RTUSBBulkRxComplete status=0 len=90 PendingRx=6
rt2570: --->RTUSBBulkRxComplete status=0 len=134 PendingRx=5
Kernel panic: Die called

Core of 0 bytes written
Panic logged[/codehnuycqqb]

Edit This appears to be a bad call to rt2570_dbgprint (0xc01ec070) from PeriodicExec (0xc01f0150).


28-10-2008 12:34:53

The latest status I can load the rt2570 module, I've reduced the number of unaligned accesses (I had to add 3 bytes of padding to the RX_CONTEXT struct) and the kernel panic has gone away for now.

I've compiled wireless-tools 29 and loaded it up on the TiVo. It seems like it's working but doesn't actually work

[code27fvond6]$ iwconfig rausb0
Warning: Driver for device rausb0 recommend version 16 of Wireless Extension,
but has been compiled with version 14, therefore some driver features
may not be available...

rausb0 RT2500USB WLAN ESSID:"Panoptic" Nickname:"TiVo"
Mode:Managed Frequency=2.412 GHz Bit Rate=11 Mb/s
RTS thr:off Fragment thr:off
Encryption key:off
Link Quality=0/100 Signal level:-120 dBm Noise level:-99 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0

$ iwlist rausb0 scan
Warning: Driver for device rausb0 recommend version 16 of Wireless Extension,
but has been compiled with version 14, therefore some driver features
may not be available...

rausb0 No scan results

$ dmesg
rt2570: <-- rtusb_ioctl_giwrange
rt2570: ==> rtusb_ioctl_siwscan
rt2570: MlmeEnqueue, num=3
rt2570: <== rtusb_ioctl_siwscan started
rt2570: rtusb_ioctl_giwscan. 0 BSS returned[/code27fvond6]

So, at this point, I'm guessing that some of the messing around I did in order to eliminate the unaligned accesses has caused the driver to stop operating correctly. Any tips on what debugging information to look at to try and figure out where?


28-10-2008 15:36:20

Hi dossy,

Well, you're doing a lot of work here. It looks like one big problem is alignment requirements.

If you look in rtmp_type.h, you'll see a macro called ALIGN_USB_RCV. Could you try changing things so that that's turned on and see what happens? The general approach is to identify structure members with platform-specific alignment requirements and use that macro, or something like it, on them.

Also, it would be very helpful if you could provide a sorted list of gcc's predefined constants for your target environment e.g. (all one line)[code2qoilhip]touch /tmp/dummy_file.c; gcc -E -dM /tmp/dummy_file.c;\rm /tmp/dummy_file.c)|sort|gzip ><choose-a-name>.gz[/code2qoilhip]Then attach the gzipped file to a post here. That will give me information I need to handle any additional MIPS requirements.



28-10-2008 16:21:43

If you look in rtmp_type.h, you'll see a macro called ALIGN_USB_RCV. Could you try changing things so that that's turned on and see what happens? The general approach is to identify structure members with platform-specific alignment requirements and use that macro, or something like it, on them.[/quote1j1uqe78]

Thank you for looking at this, Vern! I'll experiment with ALIGN_USB_RCV to 4 bytes as MIPS wants word alignment and uses 32-bit words.

Also, it would be very helpful if you could provide a sorted list of gcc's predefined constants for your target environment e.g. (all one line)[code1j1uqe78]touch /tmp/dummy_file.c; gcc -E -dM /tmp/dummy_file.c;\rm /tmp/dummy_file.c)|sort|gzip ><choose-a-name>.gz[/code1j1uqe78]Then attach the gzipped file to a post here. That will give me information I need to handle any additional MIPS requirements.[/quote1j1uqe78]

You got it - see attached.


28-10-2008 19:44:46

Hi dossy,

According to the constants you supplied, it looks like you're using GCC 3, which is a little old. Before proceeding further, you might try upgrading to gcc 4.1 (not 4.2, there's a big fat warning in the 2.4 kernel source about that).

After doing so, you may find there are kernel compile problems. To fix them try this patch[/urlf78fnrns].



28-10-2008 20:12:01

I can try to build a GCC 4.1 MIPS cross-compiler, but I'm hoping that isn't the root cause of all the issues I'm having - do you think it really could be?

Also, the patch you attached only updates the i386 kernel bits - not the mips stuff. I don't think that patch would be of much use for me, right?


30-10-2008 18:33:41


The rt2570 driver is compiled and working with minimal unaligned access traps on my TiVo Series 2 SA MIPS box. I'm attaching my patch against rt2570-cvs-2008102616.

If you wouldn't mind reviewing it and letting me know what you think, I'd really appreciate it. Thanks.


31-10-2008 17:19:17

Hi dossy,

Thanks for your efforts and investigation. A large part of the fixes you've created in your patch apply to all the legacy drivers; so you're really providing a benefit here.

The changes to rt_config.h and rtmp_type.h are needed and you should be seeing them soon in the hourly tarballs.These fixes also apply to the other legacy drivers and you'll see them show up in them shortly as well.

The other changes are confusing to me. They all seem to be doing a "shift and or" operation that does basically the same thing that "le16_to_cpu" does when expanded in a big endian environment. That expansion is determined entirely by the gcc build environment, *not* by anything defined during the driver's make process. If le16_to_cpu & co. are not doing their job, I think something more serious is awry that needs to be fixed; so I think we need to look into this part some more before putting anything in CVS.

Re. rtusb_main.c
The free_netdev change causes a compile error under 2.4.36. As of 2.4.23 at least, free_netdev does exist. So I think the proper thing to do here is to add a conditional to rt_config.h to provide it if compiling for a kernel earlier than the earliest 2.4 series kernel in which it does exist. It would be great if you could download and grep the 2.4.21 and 2.4.22 patch files to find out. On my system, free_netdev is defined in <souce-path>/include/linux/netdevice.h.

Thanks again,


31-10-2008 18:06:41


Thanks for reviewing the patch!

The byte-swapping macros compile down to lw/sw and lhu/shu MIPS assembly which requires word and half-word aligned addresses. The data structures in the rt2xxx drivers aren't aligned properly in many cases, so what I did was force unoptimized byte-swapping which doesn't trigger the unaligned access traps. (The unoptimized byte-swapping is still orders of magnitude faster than triggering repeated unaligned access traps, trust me.)

I'll try to identify which Linux kernel version introduced free_netdev and adjust the patch accordingly.



02-11-2008 16:21:08

Hi dossy,

Mmm. Vern do some googling. Vern start to understand. Looks like an alignment trap is not really a failure; it's just the mips way of handling a 16(32) bit access aligned on an 8(16) bit boundary. Is that right?

Anyway, looking at the ptr value you printed in the sanity check routine, I found a likely candidate for the cause in the MLME_QUEUE structure alignment. Could you try the attached patch on a vanilla copy of the latest CVS and see if it reduces the number of alignment faults?



11-11-2008 17:20:31

I'm also trying to get the driver to work on a MIPS processor (micronas 7108). I'm using a 2.6.12 source tree and gcc 3.3.4, and I can't easily move to a newer kernel. The 1.1.0-b2 version of the driver compiles fine and I can load the rt2570.ko module, and I can see the device in iwconfig. The problem is when I issue the "ifconfig rausb0 up" command I get "RTUSB --> NICInitTransmit" from the debug and then I keep getting "--->USB_ResetDevice" messages.

I downloaded the rt2570-csv-2008111110 csv version and applied the patch posted on this thread rt2570-tivo-mips.patch, but the module won't compile. I get the the following error "rtusb_main.c1468 error too few arguments to function `try_to_freeze'"



11-11-2008 17:41:00

Hi pthomas,

The line number you cite for the error message doesn't correspond to the latest CVS. Could you download the current CVS tarball and try it *without* any patch? (The latest CVS should handle mips big endian compiles correctly.)

If you still get compile errors, please attach a copy of your make output to a posting here.



11-11-2008 17:50:22

I download the version here [url1wrcvb3l]http://rt2x00.serialmonkey.com/rt2570-cvs-daily.tar.gz[/url1wrcvb3l]. When it's untared the folder name looks like it has todays dade code '2008111110'. Here is the whole output from the unpatched version. Let me know if I should be getting the source from somewhere else.


[code1wrcvb3l]make[1]: Entering directory `/home/raid1/micronas/khacking/CYPHER-SDK-1-5-0-RC4/linux-2.6.12-rc2-wis'
CC [M] /home/raid1/micronas/khacking/rt2570-cvs-2008111110/Module/rtusb_main.o
In file included from /home/raid1/micronas/khacking/rt2570-cvs-2008111110/Module/rtusb_main.c:36:
/home/raid1/micronas/khacking/rt2570-cvs-2008111110/Module/rt_config.h:106:27: linux/freezer.h: No such file or directory
/home/raid1/micronas/khacking/rt2570-cvs-2008111110/Module/rtusb_main.c: In function `MlmeThread':
/home/raid1/micronas/khacking/rt2570-cvs-2008111110/Module/rtusb_main.c:1438: warning: implicit declaration of function `set_freezable'
/home/raid1/micronas/khacking/rt2570-cvs-2008111110/Module/rtusb_main.c:1444: error: too few arguments to function `try_to_freeze'
/home/raid1/micronas/khacking/rt2570-cvs-2008111110/Module/rtusb_main.c: In function `RTUSBCmdThread':
/home/raid1/micronas/khacking/rt2570-cvs-2008111110/Module/rtusb_main.c:1494: error: too few arguments to function `try_to_freeze'
/home/raid1/micronas/khacking/rt2570-cvs-2008111110/Module/rtusb_main.c: At top level:
/home/raid1/micronas/khacking/rt2570-cvs-2008111110/Module/rtusb_main.c:240: warning: `rt2570_suspend' declared `static' but never defined
/home/raid1/micronas/khacking/rt2570-cvs-2008111110/Module/rtusb_main.c:241: warning: `rt2570_resume' declared `static' but never defined
make[2]: *** [/home/raid1/micronas/khacking/rt2570-cvs-2008111110/Module/rtusb_main.o] Error 1
make[1]: *** [_module_/home/raid1/micronas/khacking/rt2570-cvs-2008111110/Module] Error 2
make[1]: Leaving directory `/home/raid1/micronas/khacking/CYPHER-SDK-1-5-0-RC4/linux-2.6.12-rc2-wis'
rt2570.ko failed to build!
make: *** [module] Error 1


11-11-2008 23:12:28

OK, so I've made some progress. It looks like my source tree doesn't have include/linux/freezer.h. It looked like that didn't have to be there so I commented "#include <linux/freezer.h>" and the #if around "#define set_freezable()" and "#define try_to_freeze() 0" after that I was able to compile. Now it doesn't completely fail when I do "ifconfig rausb0 up". What happens now is that khubd is taking 99% of the CPU. One site said "The khubd thread is responsible for configuring devices". Is the driver stuck in a loop when it goes to configure the device? Is this something freezer.h would fix? Here is the output starting with insmod


insmod rt2570.ko debug=5
Using rt2570.ko
usb_rtusb_init() in rtusb_main.c
rt2570: init
rt2570: --> usb_rtusb_init
usbcore: registered new driver rt2570
rt2570: <-- usb_rtusb_init ret=0
/ # usb 1-1: new high speed USB device using musb-hcd and address 3
rt2570: --> usb_rtusb_probe (2.6)
rt2570: idVendor = 0x148f, idProduct = 0x2573
rt2570: --> PortCfgInit
rt2570: INIT bRadio=1
rt2570: <-- PortCfgInit
rt2570: --> NICInitTransmit
rt2570: <-- NICInitTransmit Status=0
rt2570: --> NICInitRecv
rt2570: <-- NICInitRecv status=0
rt2570: --> MlmeInit
rt2570: <== MlmeInitMemoryHandler Status=0
rt2570: <-- MlmeInit
rt2570: --> NICInitializeAsic

/ # ifconfig rausb0 up
rt2570: --> usb_rtusb_open: driver version 1.0.0
rt2570: driver version 1.0.0
rt2570: --> RTUSBBulkReceive, pAdapter->NextRxBulkInIndex = 0
rt2570: <-- requestBufferedRcv: Submit Rx URB ret=0
rt2570: <-- requestBufferedRcv: Submit Rx URB ret=0
rt2570: <-- requestBufferedRcv: Submit Rx URB ret=0
rt2570: <-- requestBufferedRcv: Submit Rx URB ret=0
rt2570: <-- requestBufferedRcv: Submit Rx URB ret=0
rt2570: <-- requestBufferedRcv: Submit Rx URB ret=0
rt2570: <-- requestBufferedRcv: Submit Rx URB ret=0
rt2570: <-- requestBufferedRcv: Submit Rx URB ret=0
rt2570: <-- RTUSBBulkReceive: PendingRx=8 of 8, NextRxIndex=0
rt2570: RTUSB_VendorRequest len=-145
rt2570: RTUSB_VendorRequest failed ret=-145
mgc_hcd_unlink_urb 562: *** cannot find pUrb=86625200: is not mine! this is bad (tm)
rt2570: RTUSB_VendorRequest failed ret=-145
mgc_hcd_unlink_urb 562: *** cannot find pUrb=866251a0: is not mine! this is bad (tm)

the errors continue after this, but they say similar things.


12-11-2008 17:41:20

Hi pthomas,

Thanks for jumping in and taking a look at this stuff. Here's a brief status update.

As you may have guessed, the compiler problems you're having look to be more related to using 2.6.12 than to the fact that you're targeting a mips machine.

It looks like I got the availability of freezer.h wrong I guess it really appeared with 2.6.23. It complicates matters that try_to_freeze() went from taking a parameter as of 2.6.11 to not taking one as of 2.6.13.

It'll take a little more effort to work something up that provides a clean compile over all kernel versions. I'll try to work something up over the weekend. I'm a little occupied just right now.

The "RTUSB_VendorRequest len=-145" message may be due to something else, but should probably be looked at again after the compile problems are resolved.



12-11-2008 18:02:20

Thanks for looking at this !!

Also I'm a little confused on which driver I should be using. The chip on my adapter says RT2571, and when I plug it into my desktop it loads the rt73usb, rt2x00usb and rt2x00lib modules. So I downloaded rt73-cvs-daily.tar.gz and it compiles but it has a Segmentation fault when the device plugs in.

Am I correct to use the rt73 module? Do I need only the rt73.ko module?



13-11-2008 11:06:36

Hi Paul,

Indeed, there's one RT2571 chip that use rt2570 or rt2500usb modules, but I can't remember which one. A search on the forum, should tell you that. The others chips of RT2571 serie all use rt73 or rt73usb modules. They can be identified by letters after RT2571. (i.e My USB dongle has a RT2571 WF and can use rt73 or rt73usb modules)

I think, if it is detected correctly and work with rt73usb, you can be confident that you can use rt73 module.
All you need, is this case, is verifying that you have the firmware file is the right location so it can be found an loaded by the module.
And of course, you have to blacklist non used driver to avoid conflict.

Note that if you use r2570/rt2500usb module, there is no need for a firmware file.

Edit According to your precedent post, your device report itself as idVendor = 0x148f, idProduct = 0x2573
On the list here[/urlupa1onzi] it is shown as a rt73 device.


18-11-2008 01:53:59

Hi pthomas,

Looks like Starcrasher's indicating you really need the rt73 legacy driver. Nevertheless, could you try the attached patch on the rt2570 driver? If it compiles for you cleanly, I can put it into CVS and then adapt it to the rt73 driver. We can then see what happens from there.



18-11-2008 20:21:09

Thanks for keeping up on this. The patch didn't have any effect, khubd still takes %99 of the cpu.



18-11-2008 21:08:00

Hi pthomas,

Thanks for trying the patch. Did you get a clean compile for the legacy rt2570 driver?



18-11-2008 21:10:12

Yes, it complied fine.



19-11-2008 17:38:36

Hi pthomas,

The patch has now been applied to CVS and you should see it in the hourly tarballs.

As to which driver you should be using, try playing around with lsusb and try to find the idVendor and idProduct values. See if the combination appears in either the RTUSB_DEVICES macro (rt2570 source) or RT73_USB_DEVICES (rt73 source). Depending on which one it's in, that's the driver you should use.

If it turns out to be the rt73 driver, try that, and open a thread in that forum if there are problems.



19-11-2008 18:13:13

Ok, I tried the rt73-cvs-2008111814 version and it seems to work somewhat without crashing the kernel. I am still having trouble, but it might be some USB stuff. I'll post again if I see specific problems with the adapter.