| From 05cb91085760ca378f28fc274fbf77fc4fd9886c Mon Sep 17 00:00:00 2001 |
| From: Johannes Berg <johannes.berg@intel.com> |
| Date: Fri, 28 Oct 2011 11:59:47 +0200 |
| Subject: mac80211: disable powersave for broken APs |
| |
| From: Johannes Berg <johannes.berg@intel.com> |
| |
| commit 05cb91085760ca378f28fc274fbf77fc4fd9886c upstream. |
| |
| Only AID values 1-2007 are valid, but some APs have been |
| found to send random bogus values, in the reported case an |
| AP that was sending the AID field value 0xffff, an AID of |
| 0x3fff (16383). |
| |
| There isn't much we can do but disable powersave since |
| there's no way it can work properly in this case. |
| |
| Reported-by: Bill C Riemers <briemers@redhat.com> |
| Signed-off-by: Johannes Berg <johannes.berg@intel.com> |
| Signed-off-by: John W. Linville <linville@tuxdriver.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| net/mac80211/ieee80211_i.h | 1 + |
| net/mac80211/mlme.c | 18 ++++++++++++++++-- |
| 2 files changed, 17 insertions(+), 2 deletions(-) |
| |
| --- a/net/mac80211/ieee80211_i.h |
| +++ b/net/mac80211/ieee80211_i.h |
| @@ -390,6 +390,7 @@ struct ieee80211_if_managed { |
| |
| unsigned long timers_running; /* used for quiesce/restart */ |
| bool powersave; /* powersave requested for this iface */ |
| + bool broken_ap; /* AP is broken -- turn off powersave */ |
| enum ieee80211_smps_mode req_smps, /* requested smps mode */ |
| ap_smps, /* smps mode AP thinks we're in */ |
| driver_smps_mode; /* smps mode request */ |
| --- a/net/mac80211/mlme.c |
| +++ b/net/mac80211/mlme.c |
| @@ -613,6 +613,9 @@ static bool ieee80211_powersave_allowed( |
| if (!mgd->powersave) |
| return false; |
| |
| + if (mgd->broken_ap) |
| + return false; |
| + |
| if (!mgd->associated) |
| return false; |
| |
| @@ -1467,10 +1470,21 @@ static bool ieee80211_assoc_success(stru |
| capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); |
| |
| if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) |
| - printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " |
| - "set\n", sdata->name, aid); |
| + printk(KERN_DEBUG |
| + "%s: invalid AID value 0x%x; bits 15:14 not set\n", |
| + sdata->name, aid); |
| aid &= ~(BIT(15) | BIT(14)); |
| |
| + ifmgd->broken_ap = false; |
| + |
| + if (aid == 0 || aid > IEEE80211_MAX_AID) { |
| + printk(KERN_DEBUG |
| + "%s: invalid AID value %d (out of range), turn off PS\n", |
| + sdata->name, aid); |
| + aid = 0; |
| + ifmgd->broken_ap = true; |
| + } |
| + |
| pos = mgmt->u.assoc_resp.variable; |
| ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); |
| |