diff options
Diffstat (limited to 'net/mac80211/ht.c')
| -rw-r--r-- | net/mac80211/ht.c | 80 |
1 files changed, 73 insertions, 7 deletions
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index cdc58e61d921..bb677a73b7c9 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
| @@ -34,9 +34,28 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, | |||
| 34 | 34 | ||
| 35 | ht_cap->ht_supported = true; | 35 | ht_cap->ht_supported = true; |
| 36 | 36 | ||
| 37 | ht_cap->cap = le16_to_cpu(ht_cap_ie->cap_info) & sband->ht_cap.cap; | 37 | /* |
| 38 | ht_cap->cap &= ~IEEE80211_HT_CAP_SM_PS; | 38 | * The bits listed in this expression should be |
| 39 | ht_cap->cap |= sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS; | 39 | * the same for the peer and us, if the station |
| 40 | * advertises more then we can't use those thus | ||
| 41 | * we mask them out. | ||
| 42 | */ | ||
| 43 | ht_cap->cap = le16_to_cpu(ht_cap_ie->cap_info) & | ||
| 44 | (sband->ht_cap.cap | | ||
| 45 | ~(IEEE80211_HT_CAP_LDPC_CODING | | ||
| 46 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | ||
| 47 | IEEE80211_HT_CAP_GRN_FLD | | ||
| 48 | IEEE80211_HT_CAP_SGI_20 | | ||
| 49 | IEEE80211_HT_CAP_SGI_40 | | ||
| 50 | IEEE80211_HT_CAP_DSSSCCK40)); | ||
| 51 | /* | ||
| 52 | * The STBC bits are asymmetric -- if we don't have | ||
| 53 | * TX then mask out the peer's RX and vice versa. | ||
| 54 | */ | ||
| 55 | if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC)) | ||
| 56 | ht_cap->cap &= ~IEEE80211_HT_CAP_RX_STBC; | ||
| 57 | if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)) | ||
| 58 | ht_cap->cap &= ~IEEE80211_HT_CAP_TX_STBC; | ||
| 40 | 59 | ||
| 41 | ampdu_info = ht_cap_ie->ampdu_params_info; | 60 | ampdu_info = ht_cap_ie->ampdu_params_info; |
| 42 | ht_cap->ampdu_factor = | 61 | ht_cap->ampdu_factor = |
| @@ -106,7 +125,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
| 106 | 125 | ||
| 107 | if (!skb) { | 126 | if (!skb) { |
| 108 | printk(KERN_ERR "%s: failed to allocate buffer " | 127 | printk(KERN_ERR "%s: failed to allocate buffer " |
| 109 | "for delba frame\n", sdata->dev->name); | 128 | "for delba frame\n", sdata->name); |
| 110 | return; | 129 | return; |
| 111 | } | 130 | } |
| 112 | 131 | ||
| @@ -114,10 +133,10 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
| 114 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 133 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
| 115 | memset(mgmt, 0, 24); | 134 | memset(mgmt, 0, 24); |
| 116 | memcpy(mgmt->da, da, ETH_ALEN); | 135 | memcpy(mgmt->da, da, ETH_ALEN); |
| 117 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 136 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
| 118 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 137 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
| 119 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 138 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
| 120 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | 139 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
| 121 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | 140 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) |
| 122 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); | 141 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); |
| 123 | 142 | ||
| @@ -134,7 +153,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
| 134 | mgmt->u.action.u.delba.params = cpu_to_le16(params); | 153 | mgmt->u.action.u.delba.params = cpu_to_le16(params); |
| 135 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); | 154 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); |
| 136 | 155 | ||
| 137 | ieee80211_tx_skb(sdata, skb, 1); | 156 | ieee80211_tx_skb(sdata, skb); |
| 138 | } | 157 | } |
| 139 | 158 | ||
| 140 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | 159 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, |
| @@ -166,3 +185,50 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | |||
| 166 | spin_unlock_bh(&sta->lock); | 185 | spin_unlock_bh(&sta->lock); |
| 167 | } | 186 | } |
| 168 | } | 187 | } |
| 188 | |||
| 189 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | ||
| 190 | enum ieee80211_smps_mode smps, const u8 *da, | ||
| 191 | const u8 *bssid) | ||
| 192 | { | ||
| 193 | struct ieee80211_local *local = sdata->local; | ||
| 194 | struct sk_buff *skb; | ||
| 195 | struct ieee80211_mgmt *action_frame; | ||
| 196 | |||
| 197 | /* 27 = header + category + action + smps mode */ | ||
| 198 | skb = dev_alloc_skb(27 + local->hw.extra_tx_headroom); | ||
| 199 | if (!skb) | ||
| 200 | return -ENOMEM; | ||
| 201 | |||
| 202 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
| 203 | action_frame = (void *)skb_put(skb, 27); | ||
| 204 | memcpy(action_frame->da, da, ETH_ALEN); | ||
| 205 | memcpy(action_frame->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
| 206 | memcpy(action_frame->bssid, bssid, ETH_ALEN); | ||
| 207 | action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
| 208 | IEEE80211_STYPE_ACTION); | ||
| 209 | action_frame->u.action.category = WLAN_CATEGORY_HT; | ||
| 210 | action_frame->u.action.u.ht_smps.action = WLAN_HT_ACTION_SMPS; | ||
| 211 | switch (smps) { | ||
| 212 | case IEEE80211_SMPS_AUTOMATIC: | ||
| 213 | case IEEE80211_SMPS_NUM_MODES: | ||
| 214 | WARN_ON(1); | ||
| 215 | case IEEE80211_SMPS_OFF: | ||
| 216 | action_frame->u.action.u.ht_smps.smps_control = | ||
| 217 | WLAN_HT_SMPS_CONTROL_DISABLED; | ||
| 218 | break; | ||
| 219 | case IEEE80211_SMPS_STATIC: | ||
| 220 | action_frame->u.action.u.ht_smps.smps_control = | ||
| 221 | WLAN_HT_SMPS_CONTROL_STATIC; | ||
| 222 | break; | ||
| 223 | case IEEE80211_SMPS_DYNAMIC: | ||
| 224 | action_frame->u.action.u.ht_smps.smps_control = | ||
| 225 | WLAN_HT_SMPS_CONTROL_DYNAMIC; | ||
| 226 | break; | ||
| 227 | } | ||
| 228 | |||
| 229 | /* we'll do more on status of this frame */ | ||
| 230 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
| 231 | ieee80211_tx_skb(sdata, skb); | ||
| 232 | |||
| 233 | return 0; | ||
| 234 | } | ||
