aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-rxon.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rxon.c103
1 files changed, 58 insertions, 45 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index 2d927a94074d..203ee60a82b4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -72,6 +72,34 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
72 return ret; 72 return ret;
73} 73}
74 74
75static void iwlagn_update_qos(struct iwl_priv *priv,
76 struct iwl_rxon_context *ctx)
77{
78 int ret;
79
80 if (!ctx->is_active)
81 return;
82
83 ctx->qos_data.def_qos_parm.qos_flags = 0;
84
85 if (ctx->qos_data.qos_active)
86 ctx->qos_data.def_qos_parm.qos_flags |=
87 QOS_PARAM_FLG_UPDATE_EDCA_MSK;
88
89 if (ctx->ht.enabled)
90 ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
91
92 IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
93 ctx->qos_data.qos_active,
94 ctx->qos_data.def_qos_parm.qos_flags);
95
96 ret = iwl_send_cmd_pdu(priv, ctx->qos_cmd,
97 sizeof(struct iwl_qosparam_cmd),
98 &ctx->qos_data.def_qos_parm);
99 if (ret)
100 IWL_ERR(priv, "Failed to update QoS\n");
101}
102
75static int iwlagn_update_beacon(struct iwl_priv *priv, 103static int iwlagn_update_beacon(struct iwl_priv *priv,
76 struct ieee80211_vif *vif) 104 struct ieee80211_vif *vif)
77{ 105{
@@ -97,6 +125,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
97 /* cast away the const for active_rxon in this function */ 125 /* cast away the const for active_rxon in this function */
98 struct iwl_rxon_cmd *active = (void *)&ctx->active; 126 struct iwl_rxon_cmd *active = (void *)&ctx->active;
99 bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); 127 bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
128 bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK);
100 int ret; 129 int ret;
101 130
102 lockdep_assert_held(&priv->mutex); 131 lockdep_assert_held(&priv->mutex);
@@ -176,25 +205,27 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
176 * AP station must be done after the BSSID is set to correctly 205 * AP station must be done after the BSSID is set to correctly
177 * set up filters in the device. 206 * set up filters in the device.
178 */ 207 */
179 if (ctx->ctxid == IWL_RXON_CTX_BSS) 208 if ((old_assoc && new_assoc) || !new_assoc) {
180 ret = iwlagn_disable_bss(priv, ctx, &ctx->staging); 209 if (ctx->ctxid == IWL_RXON_CTX_BSS)
181 else 210 ret = iwlagn_disable_bss(priv, ctx, &ctx->staging);
182 ret = iwlagn_disable_pan(priv, ctx, &ctx->staging); 211 else
183 if (ret) 212 ret = iwlagn_disable_pan(priv, ctx, &ctx->staging);
184 return ret; 213 if (ret)
214 return ret;
185 215
186 memcpy(active, &ctx->staging, sizeof(*active)); 216 memcpy(active, &ctx->staging, sizeof(*active));
187 217
188 /* 218 /*
189 * Un-assoc RXON clears the station table and WEP 219 * Un-assoc RXON clears the station table and WEP
190 * keys, so we have to restore those afterwards. 220 * keys, so we have to restore those afterwards.
191 */ 221 */
192 iwl_clear_ucode_stations(priv, ctx); 222 iwl_clear_ucode_stations(priv, ctx);
193 iwl_restore_stations(priv, ctx); 223 iwl_restore_stations(priv, ctx);
194 ret = iwl_restore_default_wep_keys(priv, ctx); 224 ret = iwl_restore_default_wep_keys(priv, ctx);
195 if (ret) { 225 if (ret) {
196 IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); 226 IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
197 return ret; 227 return ret;
228 }
198 } 229 }
199 230
200 /* RXON timing must be before associated RXON */ 231 /* RXON timing must be before associated RXON */
@@ -205,6 +236,9 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
205 } 236 }
206 237
207 if (new_assoc) { 238 if (new_assoc) {
239 /* QoS info may be cleared by previous un-assoc RXON */
240 iwlagn_update_qos(priv, ctx);
241
208 /* 242 /*
209 * We'll run into this code path when beaconing is 243 * We'll run into this code path when beaconing is
210 * enabled, but then we also need to send the beacon 244 * enabled, but then we also need to send the beacon
@@ -235,6 +269,8 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
235 } 269 }
236 memcpy(active, &ctx->staging, sizeof(*active)); 270 memcpy(active, &ctx->staging, sizeof(*active));
237 271
272 iwl_reprogram_ap_sta(priv, ctx);
273
238 /* IBSS beacon needs to be sent after setting assoc */ 274 /* IBSS beacon needs to be sent after setting assoc */
239 if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC)) 275 if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC))
240 if (iwlagn_update_beacon(priv, ctx->vif)) 276 if (iwlagn_update_beacon(priv, ctx->vif))
@@ -261,34 +297,6 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
261 return 0; 297 return 0;
262} 298}
263 299
264static void iwlagn_update_qos(struct iwl_priv *priv,
265 struct iwl_rxon_context *ctx)
266{
267 int ret;
268
269 if (!ctx->is_active)
270 return;
271
272 ctx->qos_data.def_qos_parm.qos_flags = 0;
273
274 if (ctx->qos_data.qos_active)
275 ctx->qos_data.def_qos_parm.qos_flags |=
276 QOS_PARAM_FLG_UPDATE_EDCA_MSK;
277
278 if (ctx->ht.enabled)
279 ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
280
281 IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
282 ctx->qos_data.qos_active,
283 ctx->qos_data.def_qos_parm.qos_flags);
284
285 ret = iwl_send_cmd_pdu(priv, ctx->qos_cmd,
286 sizeof(struct iwl_qosparam_cmd),
287 &ctx->qos_data.def_qos_parm);
288 if (ret)
289 IWL_ERR(priv, "Failed to update QoS\n");
290}
291
292int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) 300int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
293{ 301{
294 struct iwl_priv *priv = hw->priv; 302 struct iwl_priv *priv = hw->priv;
@@ -507,6 +515,11 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
507 515
508 mutex_lock(&priv->mutex); 516 mutex_lock(&priv->mutex);
509 517
518 if (WARN_ON(!ctx->vif)) {
519 mutex_unlock(&priv->mutex);
520 return;
521 }
522
510 if (changes & BSS_CHANGED_BEACON_INT) 523 if (changes & BSS_CHANGED_BEACON_INT)
511 force = true; 524 force = true;
512 525