So here's the v2 of the patch. It's been thoroughly tested and the warnings
are avoided now. Additionally, I threw in improvements in the modified
functions. Regrettably, one change I had to leave out was modernizing the
parameters in cfg80211_get_bss(), since it made the warning on NULL bss from
wl_notify_roaming_status() reappear, no matter what I tried.
One piece of advise: sometimes the driver will fail to connect, just as it did
before. NetworkManager will prompt for the password but it won't join.
Connecting manually through the networks list will succeed, however it may be
necessary to retry a few times.
Enabling the debug information we can see how, upon a successful connection,
two EAPOL_MSG events are ignored by the driver, whereas on unsuccessful ones,
they keep popping until we are DEAUTHenticated.
If anyone at Broadcom ever reads this, please give some love to this driver.
Or better yet, push for it being open sourced. We would all be very grateful.
--- a/amd64/src/wl/sys/wl_cfg80211_hybrid.c
+++ b/amd64/src/wl/sys/wl_cfg80211_hybrid.c
@@ -1968,7 +1968,7 @@
if (dtoh32(bi->length) > WL_BSS_INFO_MAX) {
WL_DBG(("Beacon is larger than buffer. Discarding\n"));
- return err;
+ return -E2BIG;
}
notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt) - sizeof(u8) +
WL_BSS_INFO_MAX, GFP_KERNEL);
@@ -1992,9 +1992,15 @@
beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
wl_rst_ie(wl);
- wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
- wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX -
+ err = wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
+ if (err)
+ goto inform_single_bss_out;
+
+ err = wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX -
offsetof(struct wl_cfg80211_bss_info, frame_buf));
+ if (err)
+ goto inform_single_bss_out;
+
notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt, u.beacon.variable) +
wl_get_ielen(wl);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
@@ -2006,14 +2012,14 @@
#endif
if (freq == 0) {
WL_ERR(("Invalid channel, fail to chcnage channel to freq\n"));
- kfree(notif_bss_info);
- return -EINVAL;
+ err = -EINVAL;
+ goto inform_single_bss_out;
}
channel = ieee80211_get_channel(wiphy, freq);
if (unlikely(!channel)) {
WL_ERR(("ieee80211_get_channel error\n"));
- kfree(notif_bss_info);
- return -EINVAL;
+ err = -EINVAL;
+ goto inform_single_bss_out;
}
WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM\n",
@@ -2021,28 +2027,37 @@
mgmt->u.beacon.capab_info, &bi->BSSID));
signal = notif_bss_info->rssi * 100;
- cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
- le16_to_cpu(notif_bss_info->frame_len), signal, GFP_KERNEL);
- if (unlikely(!cbss)) {
- WL_ERR(("cfg80211_inform_bss_frame error\n"));
- kfree(notif_bss_info);
- return -EINVAL;
- }
- notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
- notify_ielen = le32_to_cpu(bi->ie_length);
+ if (!wl->scan_request) {
+ cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
+ le16_to_cpu(notif_bss_info->frame_len), signal, GFP_KERNEL);
+ if (unlikely(!cbss)) {
+ WL_ERR(("cfg80211_inform_bss_frame error\n"));
+ err = -ENOMEM;
+ goto inform_single_bss_out;
+ }
+ } else {
+ notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
+ notify_ielen = le32_to_cpu(bi->ie_length);
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
- cbss = cfg80211_inform_bss(wiphy, channel, (const u8 *)(bi->BSSID.octet),
- 0, beacon_proberesp->capab_info, beacon_proberesp->beacon_int,
- (const u8 *)notify_ie, notify_ielen, signal, GFP_KERNEL);
+ cbss = cfg80211_inform_bss(wiphy, channel, (const u8 *)(bi->BSSID.octet),
+ 0, beacon_proberesp->capab_info, beacon_proberesp->beacon_int,
+ (const u8 *)notify_ie, notify_ielen, signal, GFP_KERNEL);
#else
- cbss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, (const u8 *)(bi->BSSID.octet),
- 0, beacon_proberesp->capab_info, beacon_proberesp->beacon_int,
- (const u8 *)notify_ie, notify_ielen, signal, GFP_KERNEL);
+ cbss = cfg80211_inform_bss(wiphy, channel,
+wl->active_scan ?
+CFG80211_BSS_FTYPE_PRESP : CFG80211_BSS_FTYPE_BEACON,
+(const u8 *)(bi->BSSID.octet), 0,
+beacon_proberesp->capab_info,
+beacon_proberesp->beacon_int,
+(const u8 *)notify_ie, notify_ielen, signal, GFP_KERNEL);
#endif
-
- if (unlikely(!cbss))
- return -ENOMEM;
+ if (unlikely(!cbss)) {
+ WL_ERR(("cfg80211_inform_bss error\n"));
+ err = -ENOMEM;
+ goto inform_single_bss_out;
+ }
+ }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
cfg80211_put_bss(wiphy, cbss);
@@ -2050,6 +2065,7 @@
cfg80211_put_bss(cbss);
#endif
+inform_single_bss_out:
kfree(notif_bss_info);
return err;
@@ -2316,6 +2332,9 @@
if (err)
goto update_bss_info_out;
+ bss = cfg80211_get_bss(wl_to_wiphy(wl), NULL, (s8 *)&wl->bssid,
+ ssid->SSID, ssid->SSID_len, WL