00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <linux/ieee80211.h>
00017 #include <linux/export.h>
00018 #include <net/mac80211.h>
00019 #include "ieee80211_i.h"
00020 #include "rate.h"
00021
00022 void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
00023 struct ieee80211_ht_cap *ht_cap_ie,
00024 struct ieee80211_sta_ht_cap *ht_cap)
00025 {
00026 u8 ampdu_info, tx_mcs_set_cap;
00027 int i, max_tx_streams;
00028
00029 BUG_ON(!ht_cap);
00030
00031 memset(ht_cap, 0, sizeof(*ht_cap));
00032
00033 if (!ht_cap_ie || !sband->ht_cap.ht_supported)
00034 return;
00035
00036 ht_cap->ht_supported = true;
00037
00038
00039
00040
00041
00042
00043
00044 ht_cap->cap = le16_to_cpu(ht_cap_ie->cap_info) &
00045 (sband->ht_cap.cap |
00046 ~(IEEE80211_HT_CAP_LDPC_CODING |
00047 IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
00048 IEEE80211_HT_CAP_GRN_FLD |
00049 IEEE80211_HT_CAP_SGI_20 |
00050 IEEE80211_HT_CAP_SGI_40 |
00051 IEEE80211_HT_CAP_DSSSCCK40));
00052
00053
00054
00055
00056 if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC))
00057 ht_cap->cap &= ~IEEE80211_HT_CAP_RX_STBC;
00058 if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC))
00059 ht_cap->cap &= ~IEEE80211_HT_CAP_TX_STBC;
00060
00061 ampdu_info = ht_cap_ie->ampdu_params_info;
00062 ht_cap->ampdu_factor =
00063 ampdu_info & IEEE80211_HT_AMPDU_PARM_FACTOR;
00064 ht_cap->ampdu_density =
00065 (ampdu_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2;
00066
00067
00068 tx_mcs_set_cap = sband->ht_cap.mcs.tx_params;
00069
00070
00071 ht_cap->mcs.tx_params = ht_cap_ie->mcs.tx_params;
00072
00073
00074 if (!(tx_mcs_set_cap & IEEE80211_HT_MCS_TX_DEFINED))
00075 return;
00076
00077
00078 if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_RX_DIFF)
00079 max_tx_streams =
00080 ((tx_mcs_set_cap & IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
00081 >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1;
00082 else
00083 max_tx_streams = IEEE80211_HT_MCS_TX_MAX_STREAMS;
00084
00085
00086
00087
00088
00089
00090
00091
00092 for (i = 0; i < max_tx_streams; i++)
00093 ht_cap->mcs.rx_mask[i] =
00094 sband->ht_cap.mcs.rx_mask[i] & ht_cap_ie->mcs.rx_mask[i];
00095
00096 if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION)
00097 for (i = IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE;
00098 i < IEEE80211_HT_MCS_MASK_LEN; i++)
00099 ht_cap->mcs.rx_mask[i] =
00100 sband->ht_cap.mcs.rx_mask[i] &
00101 ht_cap_ie->mcs.rx_mask[i];
00102
00103
00104 if (sband->ht_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1)
00105 ht_cap->mcs.rx_mask[32/8] |= 1;
00106 }
00107
00108 void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx)
00109 {
00110 int i;
00111
00112 cancel_work_sync(&sta->ampdu_mlme.work);
00113
00114 for (i = 0; i < STA_TID_NUM; i++) {
00115 __ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR, tx);
00116 __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT,
00117 WLAN_REASON_QSTA_LEAVE_QBSS, tx);
00118 }
00119 }
00120
00121 void ieee80211_ba_session_work(struct work_struct *work)
00122 {
00123 struct sta_info *sta =
00124 container_of(work, struct sta_info, ampdu_mlme.work);
00125 struct tid_ampdu_tx *tid_tx;
00126 int tid;
00127
00128
00129
00130
00131
00132
00133
00134 if (test_sta_flag(sta, WLAN_STA_BLOCK_BA))
00135 return;
00136
00137 mutex_lock(&sta->ampdu_mlme.mtx);
00138 for (tid = 0; tid < STA_TID_NUM; tid++) {
00139 if (test_and_clear_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired))
00140 ___ieee80211_stop_rx_ba_session(
00141 sta, tid, WLAN_BACK_RECIPIENT,
00142 WLAN_REASON_QSTA_TIMEOUT, true);
00143
00144 if (test_and_clear_bit(tid,
00145 sta->ampdu_mlme.tid_rx_stop_requested))
00146 ___ieee80211_stop_rx_ba_session(
00147 sta, tid, WLAN_BACK_RECIPIENT,
00148 WLAN_REASON_UNSPECIFIED, true);
00149
00150 tid_tx = sta->ampdu_mlme.tid_start_tx[tid];
00151 if (tid_tx) {
00152
00153
00154
00155
00156 spin_lock_bh(&sta->lock);
00157
00158 sta->ampdu_mlme.tid_start_tx[tid] = NULL;
00159
00160 if (sta->ampdu_mlme.tid_tx[tid])
00161 kfree(tid_tx);
00162 else
00163 ieee80211_assign_tid_tx(sta, tid, tid_tx);
00164 spin_unlock_bh(&sta->lock);
00165
00166 ieee80211_tx_ba_session_handle_start(sta, tid);
00167 continue;
00168 }
00169
00170 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
00171 if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP,
00172 &tid_tx->state))
00173 ___ieee80211_stop_tx_ba_session(sta, tid,
00174 WLAN_BACK_INITIATOR,
00175 true);
00176 }
00177 mutex_unlock(&sta->ampdu_mlme.mtx);
00178 }
00179
00180 void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
00181 const u8 *da, u16 tid,
00182 u16 initiator, u16 reason_code)
00183 {
00184 struct ieee80211_local *local = sdata->local;
00185 struct sk_buff *skb;
00186 struct ieee80211_mgmt *mgmt;
00187 u16 params;
00188
00189 skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
00190 if (!skb)
00191 return;
00192
00193 skb_reserve(skb, local->hw.extra_tx_headroom);
00194 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
00195 memset(mgmt, 0, 24);
00196 memcpy(mgmt->da, da, ETH_ALEN);
00197 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
00198 if (sdata->vif.type == NL80211_IFTYPE_AP ||
00199 sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
00200 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
00201 else if (sdata->vif.type == NL80211_IFTYPE_STATION)
00202 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
00203
00204 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
00205 IEEE80211_STYPE_ACTION);
00206
00207 skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba));
00208
00209 mgmt->u.action.category = WLAN_CATEGORY_BACK;
00210 mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA;
00211 params = (u16)(initiator << 11);
00212 params |= (u16)(tid << 12);
00213
00214 mgmt->u.action.u.delba.params = cpu_to_le16(params);
00215 mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
00216
00217 ieee80211_tx_skb(sdata, skb);
00218 }
00219
00220 void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
00221 struct sta_info *sta,
00222 struct ieee80211_mgmt *mgmt, size_t len)
00223 {
00224 u16 tid, params;
00225 u16 initiator;
00226
00227 params = le16_to_cpu(mgmt->u.action.u.delba.params);
00228 tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12;
00229 initiator = (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) >> 11;
00230
00231 #ifdef CONFIG_MAC80211_HT_DEBUG
00232 if (net_ratelimit())
00233 printk(KERN_DEBUG "delba from %pM (%s) tid %d reason code %d\n",
00234 mgmt->sa, initiator ? "initiator" : "recipient", tid,
00235 le16_to_cpu(mgmt->u.action.u.delba.reason_code));
00236 #endif
00237
00238 if (initiator == WLAN_BACK_INITIATOR)
00239 __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0,
00240 true);
00241 else
00242 __ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
00243 true);
00244 }
00245
00246 int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
00247 enum ieee80211_smps_mode smps, const u8 *da,
00248 const u8 *bssid)
00249 {
00250 struct ieee80211_local *local = sdata->local;
00251 struct sk_buff *skb;
00252 struct ieee80211_mgmt *action_frame;
00253
00254
00255 skb = dev_alloc_skb(27 + local->hw.extra_tx_headroom);
00256 if (!skb)
00257 return -ENOMEM;
00258
00259 skb_reserve(skb, local->hw.extra_tx_headroom);
00260 action_frame = (void *)skb_put(skb, 27);
00261 memcpy(action_frame->da, da, ETH_ALEN);
00262 memcpy(action_frame->sa, sdata->dev->dev_addr, ETH_ALEN);
00263 memcpy(action_frame->bssid, bssid, ETH_ALEN);
00264 action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
00265 IEEE80211_STYPE_ACTION);
00266 action_frame->u.action.category = WLAN_CATEGORY_HT;
00267 action_frame->u.action.u.ht_smps.action = WLAN_HT_ACTION_SMPS;
00268 switch (smps) {
00269 case IEEE80211_SMPS_AUTOMATIC:
00270 case IEEE80211_SMPS_NUM_MODES:
00271 WARN_ON(1);
00272 case IEEE80211_SMPS_OFF:
00273 action_frame->u.action.u.ht_smps.smps_control =
00274 WLAN_HT_SMPS_CONTROL_DISABLED;
00275 break;
00276 case IEEE80211_SMPS_STATIC:
00277 action_frame->u.action.u.ht_smps.smps_control =
00278 WLAN_HT_SMPS_CONTROL_STATIC;
00279 break;
00280 case IEEE80211_SMPS_DYNAMIC:
00281 action_frame->u.action.u.ht_smps.smps_control =
00282 WLAN_HT_SMPS_CONTROL_DYNAMIC;
00283 break;
00284 }
00285
00286
00287 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
00288 ieee80211_tx_skb(sdata, skb);
00289
00290 return 0;
00291 }
00292
00293 void ieee80211_request_smps_work(struct work_struct *work)
00294 {
00295 struct ieee80211_sub_if_data *sdata =
00296 container_of(work, struct ieee80211_sub_if_data,
00297 u.mgd.request_smps_work);
00298
00299 mutex_lock(&sdata->u.mgd.mtx);
00300 __ieee80211_request_smps(sdata, sdata->u.mgd.driver_smps_mode);
00301 mutex_unlock(&sdata->u.mgd.mtx);
00302 }
00303
00304 void ieee80211_request_smps(struct ieee80211_vif *vif,
00305 enum ieee80211_smps_mode smps_mode)
00306 {
00307 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
00308
00309 if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
00310 return;
00311
00312 if (WARN_ON(smps_mode == IEEE80211_SMPS_OFF))
00313 smps_mode = IEEE80211_SMPS_AUTOMATIC;
00314
00315 sdata->u.mgd.driver_smps_mode = smps_mode;
00316
00317 ieee80211_queue_work(&sdata->local->hw,
00318 &sdata->u.mgd.request_smps_work);
00319 }
00320
00321 EXPORT_SYMBOL_GPL(ieee80211_request_smps);