Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: allow disable FAT in specific configurations

This patch allows to disable FAT channel in specific configurations.

For example the configuration (8, +1), (primary channel 8, extension
channel 12) isn't permitted in U.S., but (8, -1), (primary channel 8,
extension channel 4) is. When FAT channel configuration is not
permitted, FAT channel should be reported as not supported in the
capabilities of the HT IE in association request. And sssociation is
performed on 20Mhz channel.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Emmanuel Grumbach and committed by
John W. Linville
9306102e 3c57601d

+54 -2
+2
include/linux/ieee80211.h
··· 320 320 #define IEEE80211_HT_CAP_MCS_TX_UEQM 0x10 321 321 /* 802.11n HT IE masks */ 322 322 #define IEEE80211_HT_IE_CHA_SEC_OFFSET 0x03 323 + #define IEEE80211_HT_IE_CHA_SEC_ABOVE 0x01 324 + #define IEEE80211_HT_IE_CHA_SEC_BELOW 0x03 323 325 #define IEEE80211_HT_IE_CHA_WIDTH 0x04 324 326 #define IEEE80211_HT_IE_HT_PROTECTION 0x0003 325 327 #define IEEE80211_HT_IE_NON_GF_STA_PRSNT 0x0004
+6
include/net/wireless.h
··· 39 39 * on this channel. 40 40 * @IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel. 41 41 * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel. 42 + * @IEEE80211_CHAN_NO_FAT_ABOVE: extension channel above this channel 43 + * is not permitted. 44 + * @IEEE80211_CHAN_NO_FAT_BELOW: extension channel below this channel 45 + * is not permitted. 42 46 */ 43 47 enum ieee80211_channel_flags { 44 48 IEEE80211_CHAN_DISABLED = 1<<0, 45 49 IEEE80211_CHAN_PASSIVE_SCAN = 1<<1, 46 50 IEEE80211_CHAN_NO_IBSS = 1<<2, 47 51 IEEE80211_CHAN_RADAR = 1<<3, 52 + IEEE80211_CHAN_NO_FAT_ABOVE = 1<<4, 53 + IEEE80211_CHAN_NO_FAT_BELOW = 1<<5, 48 54 }; 49 55 50 56 /**
+2
net/mac80211/ieee80211_i.h
··· 92 92 size_t wmm_ie_len; 93 93 u8 *ht_ie; 94 94 size_t ht_ie_len; 95 + u8 *ht_add_ie; 96 + size_t ht_add_ie_len; 95 97 #ifdef CONFIG_MAC80211_MESH 96 98 u8 *mesh_id; 97 99 size_t mesh_id_len;
+44 -2
net/mac80211/mlme.c
··· 808 808 809 809 /* wmm support is a must to HT */ 810 810 if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && 811 - sband->ht_info.ht_supported) { 812 - __le16 tmp = cpu_to_le16(sband->ht_info.cap); 811 + sband->ht_info.ht_supported && bss->ht_add_ie) { 812 + struct ieee80211_ht_addt_info *ht_add_info = 813 + (struct ieee80211_ht_addt_info *)bss->ht_add_ie; 814 + u16 cap = sband->ht_info.cap; 815 + __le16 tmp; 816 + u32 flags = local->hw.conf.channel->flags; 817 + 818 + switch (ht_add_info->ht_param & IEEE80211_HT_IE_CHA_SEC_OFFSET) { 819 + case IEEE80211_HT_IE_CHA_SEC_ABOVE: 820 + if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) { 821 + cap &= ~IEEE80211_HT_CAP_SUP_WIDTH; 822 + cap &= ~IEEE80211_HT_CAP_SGI_40; 823 + } 824 + break; 825 + case IEEE80211_HT_IE_CHA_SEC_BELOW: 826 + if (flags & IEEE80211_CHAN_NO_FAT_BELOW) { 827 + cap &= ~IEEE80211_HT_CAP_SUP_WIDTH; 828 + cap &= ~IEEE80211_HT_CAP_SGI_40; 829 + } 830 + break; 831 + } 832 + 833 + tmp = cpu_to_le16(cap); 813 834 pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2); 814 835 *pos++ = WLAN_EID_HT_CAPABILITY; 815 836 *pos++ = sizeof(struct ieee80211_ht_cap); ··· 2285 2264 kfree(bss->rsn_ie); 2286 2265 kfree(bss->wmm_ie); 2287 2266 kfree(bss->ht_ie); 2267 + kfree(bss->ht_add_ie); 2288 2268 kfree(bss_mesh_id(bss)); 2289 2269 kfree(bss_mesh_cfg(bss)); 2290 2270 kfree(bss); ··· 2660 2638 kfree(bss->ht_ie); 2661 2639 bss->ht_ie = NULL; 2662 2640 bss->ht_ie_len = 0; 2641 + } 2642 + 2643 + if (elems.ht_info_elem && 2644 + (!bss->ht_add_ie || 2645 + bss->ht_add_ie_len != elems.ht_info_elem_len || 2646 + memcmp(bss->ht_add_ie, elems.ht_info_elem, 2647 + elems.ht_info_elem_len))) { 2648 + kfree(bss->ht_add_ie); 2649 + bss->ht_add_ie = 2650 + kmalloc(elems.ht_info_elem_len + 2, GFP_ATOMIC); 2651 + if (bss->ht_add_ie) { 2652 + memcpy(bss->ht_add_ie, elems.ht_info_elem - 2, 2653 + elems.ht_info_elem_len + 2); 2654 + bss->ht_add_ie_len = elems.ht_info_elem_len + 2; 2655 + } else 2656 + bss->ht_add_ie_len = 0; 2657 + } else if (!elems.ht_info_elem && bss->ht_add_ie) { 2658 + kfree(bss->ht_add_ie); 2659 + bss->ht_add_ie = NULL; 2660 + bss->ht_add_ie_len = 0; 2663 2661 } 2664 2662 2665 2663 bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);