Fixing the Broadcom BCM4331 wireless drivers on Ubuntu 13.10
How to restore stable WiFi on the Broadcom Corporation BCM4331 wireless chip after upgrading from Ubuntu 13.04 (Raring) to 13.10 (Saucy Salamander).
Introduction
I have a Macbook Pro 9.2 at work, though the first thing I did upon receiving it was to install (Ubuntu) Linux on it. Surprisingly, after figuring out the nuances of the EFI booting, everything worked surprisingly well. This included wireless, bluetooth and backlight control, all working out of the box.
Now, this all changed when I upgraded to 13.10 however. Suddenly, I no
longer found my wireless to be particularly stable. At home, this manifested
itself in particularly unstable SSH sessions, though oddly, it was usually
fine besides that. At work however, the experience was much worse, giving
frequent disconnects, packet loss and overall high latency. The kernel log
was also full of ERROR @wl_cfg80211_get_station : Wrong Mac address
, though
I was seeing this on my home network as well.
Some searching around quickly revealed there are lots of people with similar issues, the general concensus being Broadcom’s proprietary drivers are just, well, crap. (There’s also an opensource driver which does work with the chip in this Macbook, but after trying it out, I can safely say that experience was even worse.)
Fed up with the situation at last, I decided to try and downgrade back to the drivers shipped with 13.04 in an effort to get back to that previous level of stability. To make a long story short, after some research and experimentation, I have successfully downgraded and am now enjoying a stable wireless experience again. The rest of this post will be a guide on how to perform these steps yourself as well, in case you find yourself in the same boat I was in.
Downgrading to 6.20.155.1+bdcom-0ubuntu6
First, grab the 6.20.155.1+bdcom-0ubuntu6 version of bcmwl-kernel-source and then install it. It will fail to build the kernel module once dkms kicks in, but that’s okay. It won’t prevent the package itself from installing.
# Find a mirror close to you at:
# http://packages.ubuntu.com/raring/i385/bcmwl-kernel-source/download (i386)
# or:
# http://packages.ubuntu.com/raring/amd64/bcmwl-kernel-source/download (amd64, like this macbook)
wget http://nl.archive.ubuntu.com/ubuntu/pool/restricted/b/bcmwl/bcmwl-kernel-source_6.20.155.1+bdcom-0ubuntu6_amd64.deb
# And then install it
dpkg -i bcmwl-kernel-source_6.20.155.1+bdcom-0ubuntu6_amd64.deb
To make it build on the 3.11 kernel currently shipped with Ubuntu 13.10, two extra patches are needed. I managed to find these in the 6.30.223.141+bdcom-0ubuntu1 version of bcmwl-kernel-source that we just replaced, but for your convenience I’ve mirrorred them here as well:
The first patch needs to be patched (har har) however to apply cleanly. If you downloaded my version above, I’ve already done this for you.
--- 0008-add-support-for-linux-3.9.0.patch
+++ 0008-add-support-for-linux-3.9.0.patch
@@ -4,8 +4,8 @@
Subject: [PATCH 1/1] Add support for Linux 3.9
---
---- a/src/wl/sys/wl_cfg80211_hybrid.c
-+++ a/src/wl/sys/wl_cfg80211_hybrid.c
+--- a/src/wl/sys/wl_cfg80211.c
++++ a/src/wl/sys/wl_cfg80211.c
@@ -2048,7 +2048,11 @@
ie_len = (size_t)(ies->len);
rcu_read_unlock();
Place these into /usr/src/bcmwl-6.20.155.1+bdcom/patches
, then adjust
/usr/src/bcmwl-6.20.155.1+bdcom/dkms.conf
to use them:
--- /usr/src/bcmwl-6.20.155.1+bdcom/dkms.conf
+++ /usr/src/bcmwl-6.20.155.1+bdcom/dkms.conf
@@ -12,6 +12,8 @@
PATCH[4]="0005-add-support-for-linux-3.4.0.patch"
PATCH[5]="0006-add-support-for-linux-3.8.0.patch"
PATCH[6]="0007-nl80211-move-scan-API-to-wdev.patch"
+PATCH[7]="0008-add-support-for-linux-3.9.0.patch"
+PATCH[8]="0009-add-support-for-linux-3.10.0.patch"
#PATCH_MATCH[3]="^3.[23456]"
#PATCH_MATCH[4]="^3.[56]"
AUTOINSTALL="yes"
At this point, it should build and install successfully:
dkms build -m bcmwl -v 6.20.155.1+bdcom && dkms install -m bcmwl -v 6.20.155.1+bdcom
Assuming that went off without a hitch, you can reload the wl
module
to use this version now (note: this will of course disconnect you):
rmmod wl && modprobe wl
To verify you really are running the 6.20.155.1 version of the driver,
you can check the last few lines of dmesg
output. It should show
Broadcom BCM4331 802.11 Hybrid Wireless Controller 6.20.155.1 (r326264)
(note the version number there).
Making sure it stays put
Finally, you’ll also want to ensure that an update doesn’t pull the
newer version back in, which would undo all the hard work you’ve just
done. This can be done by pinning
the version of bcmwl-kernel-source. Create
/etc/apt/preferences.d/bcmwl-kernel-source
with the following
contents, and you should be all set.
Package: bcmwl-kernel-source
Pin: version 6.20.155.1+bdcom*
Pin-Priority: 1001
Closing notes
None of this is officially supported by Ubuntu of course, so don’t blame
me if it doesn’t work or stops working on a kernel update some day in the
future :) That said, the procedure is safe, and if you ever want to return
back to the original state, you only have to remove the
/etc/apt/preferences.d/bcmwl-kernel-source
file to undo the pinning, then
issue an apt-get upgrade
or aptitude upgrade
to install the latest
version again.