, , , ,

This is a followup to my earlier post about configuring a Raspberry Pi for headless operation over WiFi. Since configuring my RPi, I’ve noticed that it will occasionally drop its WiFi connection after several hours. Since the RPi is headless, I’m fairly dependent on that network connection to interact with it at all. It turns out I’m not alone, and that there appears to be an easy fix. Read on for the details.

Why WiFi a Pi?

Like many users, I want to locate my RPi in a place where an electric outlet is available, but a network cable drop is not practical. The obvious solution is WiFi via USB. Since the RPi model B+ has four host ports, using a WiFi USB dongle doesn’t consume too many resources.

I bought this dongle from Adafruit mostly because I also bought the RPi from them in the same order, they were pretty clear about driver compatibility, and the price was really good.

As I documented in the earlier post, it was straightforward to get the WiFi operational, with just a little extra trickiness caused by me being stubborn about not booting to a desktop where a GUI tool could have written the configuration files for me.

Problem? What Problem?

I’ve been using that RPi for my ongoing series of posts about using the SPLear with an RPi, and often used the WiFi since it is configured. Since I no longer have a console serial port (that UART is now connected to the SPLear) whatever network I happen to be using is my only way in to the RPi.

But on several occasions where I’ve left it running a test and walked away for several hours, the network has unexpectedly gone offline.

Google Knows Everything!

I was expecting this to be a tough issue to resolve, since search terms like “Raspberry Pi”, “WiFi”, and “dropped” have many millions of hits each. Amazingly, when used together, they actually produced hits on many blog posts discussing variations on the same problem I was seeing. A top hit was to this article at Adafruit which is part of their basic education on the RPi, but which contains as an aside a fix to this very problem.

This WiFi adapter is based on a popular chip from Realtek, the 8192cu. Many inexpensive WiFi adapters are based on this chip, and it has had Linux kernel support for some time as a result. It would ordinarily seem like a safe choice. Like most modern Linux devices, its driver is loaded when needed as a “module”, and has a number of options or parameters that can be adjusted as needed.

It would appear that there is an issue with the 8192cu module’s handling of a power saving feature of the chip, when used in an RPi. The module distributed with Raspbian has this feature enabled. The consensus of the internet is that is a mistake in this platform.

The Fix is In!

Fortunately you don’t have to recompile the kernel or even the 8192cu module to fix this. You just need to create a file named /etc/modprobe.d/8192cu.conf and give it this content:

# Disable power saving
options 8192cu rtw_power_mgnt=0 rtw_enusbss=1 rtw_ips_mode=1

Be sure to edit that file as root, Adafruit suggests sudo nano /etc/modprobe.d/8192cu.conf since the nano editor is gentle for newcomers. I’ve been hanging around Unix-like systems for too long, and personally prefer vi. But choice of text editor on Unix is a very personal thing, so don’t feel pressured to try vi….

Since I made this change (and rebooted, perforce by taking the RPi home with me) it stayed connected to my home WiFi for at least 12 hours without dropping, and 7.5 hours without any user interaction.

What Did That Do?

When a module loads, the system looks in the folder /etc/modprobe.d for a file that mentions the module. There is a strong convention that files in that folder be named for the module they are configuring, but the kernel is unaware of that, and simply searches *.conf.

The file we created has a line that begins options 8192cu. That identifies the module whose options we want to set. The 8192cu module has many options, which can be listed:

pi@treepi ~ $ ls /sys/module/8192cu/parameters/
if2name           rtw_ht_enable          rtw_network_mode
ifname            rtw_hwpdn_mode         rtw_notch_filter
rtw_80211d        rtw_hwpwrp_detect      rtw_power_mgnt
rtw_ampdu_amsdu   rtw_hw_wps_pbc         rtw_rf_config
rtw_ampdu_enable  rtw_initmac            rtw_rfintfs
rtw_antdiv_cfg    rtw_ips_mode           rtw_rx_stbc
rtw_busy_thresh   rtw_lbkmode            rtw_special_rf_path
rtw_cbw40_enable  rtw_low_power          rtw_vcs_type
rtw_channel       rtw_lowrate_two_xmit   rtw_vrtl_carrier_sense
rtw_channel_plan  rtw_mac_phy_mode       rtw_wifi_spec
rtw_chip_version  rtw_max_roaming_times  rtw_wmm_enable
rtw_enusbss       rtw_mc2u_disable
rtw_force_iol     rtw_mp_mode

As is typical, there doesn’t actually seem to be any readily accessible documentation on what these options do.

That said, the default value for rtw_power_mgnt was 1. Setting it to 0 apparently skips the power saving logic and leaves the power set to active all the time. The value is selected from this enum:

enum Power_Mgnt
    PS_MODE_ACTIVE  = 0 ,
    PS_MODE_MIN         ,
    PS_MODE_MAX         ,
    PS_MODE_DTIM            ,
    PS_MODE_VOIP            ,
    PS_MODE_UAPSD           ,
    PS_MODE_IBSS            ,
    PS_MODE_WWLAN       ,
    PM_Radio_Off            ,
    PM_Card_Disable     ,

The default value for rtw_enusbss is 0. From the source, it can be 0 for “disabled” or 1 for “enabled. Other than it being heavily used in the power management code, it is unclear what this option actually controls. Google suggests that “USB SS” would refer to USB 3.0 SuperSpeed, but it isn’t at all obvious how a WiFi driver would care whether the USB connection was in SuperSpeed mode or not.

The default value for rtw_ips_mode is 1, but from the source code it could have been 0, 1, or 2 depending on what options were configured when the module was built. Setting it to 1 explicitly does no harm. It would be a value from this enum:

enum { // for ips_mode

It would be nice if there actually was some documentation on this other than the raw source code. Luckily, this recipe seems to work for me, and I can simply add my voice to the chorus observing that there was a problem that can be patched without fully understanding the issue.

Remember kids, if you have a project involving embedded systems, micro-controllers, electronics design, audio, video, or more we can help. Check out our main site and call or email us with your needs. No project is too small!

+1 626 303-1602
Cheshire Engineering Corp.
120 W Olive Ave
Monrovia, CA 91016

(Written with StackEdit.)