bool has_erp_value;
u8 erp_value;
+ bool has_ht_info;
+ struct ieee80211_ht_info ht_info;
+
/* Keep track of the corruption of the last beacon/probe response. */
u8 corrupt_data;
* @IEEE80211_BSS_VALID_WMM: WMM/UAPSD data was gathered from non-corrupt IE
* @IEEE80211_BSS_VALID_RATES: Supported rates were gathered from non-corrupt IE
* @IEEE80211_BSS_VALID_ERP: ERP flag was gathered from non-corrupt IE
+ * @IEEE80211_BSS_VALID_HT: HT information was gathered from non-corrupt IE
*
* These are bss flags that are attached to a bss in the
* @valid_data field of &struct ieee80211_bss. They show which parts
IEEE80211_BSS_VALID_DTIM = BIT(0),
IEEE80211_BSS_VALID_WMM = BIT(1),
IEEE80211_BSS_VALID_RATES = BIT(2),
- IEEE80211_BSS_VALID_ERP = BIT(3)
+ IEEE80211_BSS_VALID_ERP = BIT(3),
+ IEEE80211_BSS_VALID_HT = BIT(4)
};
static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss)
return (1 << ecw) - 1;
}
+static bool ieee80211_bss_get_htinfo(struct ieee80211_bss *bss,
+ struct ieee80211_ht_info *hti) {
+ if (bss == NULL || !bss->has_ht_info)
+ return false;
+
+ memcpy(hti, &bss->ht_info, sizeof(*hti));
+ return true;
+}
+
/*
* ieee80211_enable_ht should be called only after the operating band
* has been determined as ht configuration depends on the hw's
static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
struct ieee80211_ht_info *hti,
const u8 *bssid, u16 ap_ht_cap_flags,
- bool beacon_htcap_ie)
+ bool beacon_htcap_ie,
+ struct ieee80211_bss *bss)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband;
int hti_cfreq;
u16 ht_opmode;
bool enable_ht = true;
+ bool disable_tx_ht = false;
enum nl80211_channel_type prev_chantype;
enum nl80211_channel_type rx_channel_type = NL80211_CHAN_NO_HT;
enum nl80211_channel_type tx_channel_type;
+ struct ieee80211_ht_info bss_hti;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
prev_chantype = sdata->vif.bss_conf.channel_type;
* Netgear WNDR3700 sometimes reports 4 higher than
* the actual channel, for instance.
*/
- printk(KERN_DEBUG
- "%s: Wrong control channel in association"
- " response: configured center-freq: %d"
- " hti-cfreq: %d hti->control_chan: %d"
- " band: %d. Disabling HT.\n",
- sdata->name,
- local->hw.conf.channel->center_freq,
- hti_cfreq, hti->control_chan,
- sband->band);
- enable_ht = false;
+ if (ieee80211_bss_get_htinfo(bss, &bss_hti) &&
+ local->hw.conf.channel->center_freq ==
+ ieee80211_channel_to_frequency(
+ bss_hti.control_chan, sband->band)) {
+ /*
+ * If we disable HT overall, then we
+ * will have associated saying we can
+ * receive HT40, but then turned
+ * around and become deaf to it. Use
+ * the HT information from the beacon
+ * to configure receive, but restrain
+ * ourselves from ever transmitting in
+ * HT.
+ */
+ printk(KERN_DEBUG
+ "%s: Wrong control channel in "
+ " association response: configured"
+ " center-freq: %d hti-cfreq: %d "
+ " hti->control_chan: %d band: %d. "
+ " Disabling HT transmit.\n",
+ sdata->name,
+ local->hw.conf.channel->center_freq,
+ hti_cfreq, hti->control_chan,
+ sband->band);
+ hti = &bss_hti;
+ disable_tx_ht = true;
+ } else {
+ printk(KERN_DEBUG
+ "%s: Wrong control channel in "
+ " association response: configured"
+ " center-freq: %d hti-cfreq: %d "
+ " hti->control_chan: %d band: %d. "
+ " Disabling HT.\n",
+ sdata->name,
+ local->hw.conf.channel->center_freq,
+ hti_cfreq, hti->control_chan,
+ sband->band);
+ enable_ht = false;
+ }
}
if (enable_ht) {
}
tx_channel_type = ieee80211_get_tx_channel_type(local, rx_channel_type);
+ if (disable_tx_ht)
+ tx_channel_type = NL80211_CHAN_NO_HT;
if (local->tmp_channel)
local->tmp_channel_type = rx_channel_type;
!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
cbss->bssid, ap_ht_cap_flags,
- false);
+ false,
+ (struct ieee80211_bss *)
+ cbss->priv);
/* set AID and assoc capability,
* ieee80211_set_associated() will tell the driver */
rcu_read_unlock();
changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
- bssid, ap_ht_cap_flags, true);
+ bssid, ap_ht_cap_flags, true,
+ NULL);
}
/* Note: country IE parsing is done for us by cfg80211 */