aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c157
1 files changed, 130 insertions, 27 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
index 75b901b3eb1e..ffb2f4111ad0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
@@ -37,12 +37,13 @@
37#include "iwl-io.h" 37#include "iwl-io.h"
38#include "iwl-agn.h" 38#include "iwl-agn.h"
39 39
40int iwlagn_send_rxon_assoc(struct iwl_priv *priv) 40int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
41 struct iwl_rxon_context *ctx)
41{ 42{
42 int ret = 0; 43 int ret = 0;
43 struct iwl5000_rxon_assoc_cmd rxon_assoc; 44 struct iwl5000_rxon_assoc_cmd rxon_assoc;
44 const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; 45 const struct iwl_rxon_cmd *rxon1 = &ctx->staging;
45 const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; 46 const struct iwl_rxon_cmd *rxon2 = &ctx->active;
46 47
47 if ((rxon1->flags == rxon2->flags) && 48 if ((rxon1->flags == rxon2->flags) &&
48 (rxon1->filter_flags == rxon2->filter_flags) && 49 (rxon1->filter_flags == rxon2->filter_flags) &&
@@ -60,23 +61,23 @@ int iwlagn_send_rxon_assoc(struct iwl_priv *priv)
60 return 0; 61 return 0;
61 } 62 }
62 63
63 rxon_assoc.flags = priv->staging_rxon.flags; 64 rxon_assoc.flags = ctx->staging.flags;
64 rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; 65 rxon_assoc.filter_flags = ctx->staging.filter_flags;
65 rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; 66 rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
66 rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; 67 rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
67 rxon_assoc.reserved1 = 0; 68 rxon_assoc.reserved1 = 0;
68 rxon_assoc.reserved2 = 0; 69 rxon_assoc.reserved2 = 0;
69 rxon_assoc.reserved3 = 0; 70 rxon_assoc.reserved3 = 0;
70 rxon_assoc.ofdm_ht_single_stream_basic_rates = 71 rxon_assoc.ofdm_ht_single_stream_basic_rates =
71 priv->staging_rxon.ofdm_ht_single_stream_basic_rates; 72 ctx->staging.ofdm_ht_single_stream_basic_rates;
72 rxon_assoc.ofdm_ht_dual_stream_basic_rates = 73 rxon_assoc.ofdm_ht_dual_stream_basic_rates =
73 priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; 74 ctx->staging.ofdm_ht_dual_stream_basic_rates;
74 rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; 75 rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain;
75 rxon_assoc.ofdm_ht_triple_stream_basic_rates = 76 rxon_assoc.ofdm_ht_triple_stream_basic_rates =
76 priv->staging_rxon.ofdm_ht_triple_stream_basic_rates; 77 ctx->staging.ofdm_ht_triple_stream_basic_rates;
77 rxon_assoc.acquisition_data = priv->staging_rxon.acquisition_data; 78 rxon_assoc.acquisition_data = ctx->staging.acquisition_data;
78 79
79 ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, 80 ret = iwl_send_cmd_pdu_async(priv, ctx->rxon_assoc_cmd,
80 sizeof(rxon_assoc), &rxon_assoc, NULL); 81 sizeof(rxon_assoc), &rxon_assoc, NULL);
81 if (ret) 82 if (ret)
82 return ret; 83 return ret;
@@ -136,7 +137,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv,
136 continue; 137 continue;
137 } 138 }
138 139
139 delta_g = (priv->cfg->chain_noise_scale * 140 delta_g = (priv->cfg->base_params->chain_noise_scale *
140 ((s32)average_noise[default_chain] - 141 ((s32)average_noise[default_chain] -
141 (s32)average_noise[i])) / 1500; 142 (s32)average_noise[i])) / 1500;
142 143
@@ -184,7 +185,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
184 int ret; 185 int ret;
185 186
186 if ((data->state == IWL_CHAIN_NOISE_ALIVE) && 187 if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
187 iwl_is_associated(priv)) { 188 iwl_is_any_associated(priv)) {
188 struct iwl_calib_chain_noise_reset_cmd cmd; 189 struct iwl_calib_chain_noise_reset_cmd cmd;
189 190
190 /* clear data for chain noise calibration algorithm */ 191 /* clear data for chain noise calibration algorithm */
@@ -221,7 +222,8 @@ static void iwlagn_tx_cmd_protection(struct iwl_priv *priv,
221 return; 222 return;
222 } 223 }
223 224
224 if (priv->cfg->use_rts_for_aggregation && 225 if (priv->cfg->ht_params &&
226 priv->cfg->ht_params->use_rts_for_aggregation &&
225 info->flags & IEEE80211_TX_CTL_AMPDU) { 227 info->flags & IEEE80211_TX_CTL_AMPDU) {
226 *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; 228 *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
227 return; 229 return;
@@ -235,13 +237,13 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv,
235 /* data from PHY/DSP regarding signal strength, etc., 237 /* data from PHY/DSP regarding signal strength, etc.,
236 * contents are always there, not configurable by host 238 * contents are always there, not configurable by host
237 */ 239 */
238 struct iwl5000_non_cfg_phy *ncphy = 240 struct iwlagn_non_cfg_phy *ncphy =
239 (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf; 241 (struct iwlagn_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
240 u32 val, rssi_a, rssi_b, rssi_c, max_rssi; 242 u32 val, rssi_a, rssi_b, rssi_c, max_rssi;
241 u8 agc; 243 u8 agc;
242 244
243 val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]); 245 val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_AGC_IDX]);
244 agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS; 246 agc = (val & IWLAGN_OFDM_AGC_MSK) >> IWLAGN_OFDM_AGC_BIT_POS;
245 247
246 /* Find max rssi among 3 possible receivers. 248 /* Find max rssi among 3 possible receivers.
247 * These values are measured by the digital signal processor (DSP). 249 * These values are measured by the digital signal processor (DSP).
@@ -249,11 +251,14 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv,
249 * if the radio's automatic gain control (AGC) is working right. 251 * if the radio's automatic gain control (AGC) is working right.
250 * AGC value (see below) will provide the "interesting" info. 252 * AGC value (see below) will provide the "interesting" info.
251 */ 253 */
252 val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]); 254 val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_AB_IDX]);
253 rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS; 255 rssi_a = (val & IWLAGN_OFDM_RSSI_INBAND_A_BITMSK) >>
254 rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS; 256 IWLAGN_OFDM_RSSI_A_BIT_POS;
255 val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]); 257 rssi_b = (val & IWLAGN_OFDM_RSSI_INBAND_B_BITMSK) >>
256 rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS; 258 IWLAGN_OFDM_RSSI_B_BIT_POS;
259 val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_C_IDX]);
260 rssi_c = (val & IWLAGN_OFDM_RSSI_INBAND_C_BITMSK) >>
261 IWLAGN_OFDM_RSSI_C_BIT_POS;
257 262
258 max_rssi = max_t(u32, rssi_a, rssi_b); 263 max_rssi = max_t(u32, rssi_a, rssi_b);
259 max_rssi = max_t(u32, max_rssi, rssi_c); 264 max_rssi = max_t(u32, max_rssi, rssi_c);
@@ -266,12 +271,109 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv,
266 return max_rssi - agc - IWLAGN_RSSI_OFFSET; 271 return max_rssi - agc - IWLAGN_RSSI_OFFSET;
267} 272}
268 273
274static int iwlagn_set_pan_params(struct iwl_priv *priv)
275{
276 struct iwl_wipan_params_cmd cmd;
277 struct iwl_rxon_context *ctx_bss, *ctx_pan;
278 int slot0 = 300, slot1 = 0;
279 int ret;
280
281 if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS))
282 return 0;
283
284 BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
285
286 lockdep_assert_held(&priv->mutex);
287
288 ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS];
289 ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN];
290
291 /*
292 * If the PAN context is inactive, then we don't need
293 * to update the PAN parameters, the last thing we'll
294 * have done before it goes inactive is making the PAN
295 * parameters be WLAN-only.
296 */
297 if (!ctx_pan->is_active)
298 return 0;
299
300 memset(&cmd, 0, sizeof(cmd));
301
302 /* only 2 slots are currently allowed */
303 cmd.num_slots = 2;
304
305 cmd.slots[0].type = 0; /* BSS */
306 cmd.slots[1].type = 1; /* PAN */
307
308 if (ctx_bss->vif && ctx_pan->vif) {
309 int bcnint = ctx_pan->vif->bss_conf.beacon_int;
310
311 /* should be set, but seems unused?? */
312 cmd.flags |= cpu_to_le16(IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE);
313
314 if (ctx_pan->vif->type == NL80211_IFTYPE_AP &&
315 bcnint &&
316 bcnint != ctx_bss->vif->bss_conf.beacon_int) {
317 IWL_ERR(priv,
318 "beacon intervals don't match (%d, %d)\n",
319 ctx_bss->vif->bss_conf.beacon_int,
320 ctx_pan->vif->bss_conf.beacon_int);
321 } else
322 bcnint = max_t(int, bcnint,
323 ctx_bss->vif->bss_conf.beacon_int);
324 if (!bcnint)
325 bcnint = DEFAULT_BEACON_INTERVAL;
326 slot0 = bcnint / 2;
327 slot1 = bcnint - slot0;
328
329 if (test_bit(STATUS_SCAN_HW, &priv->status) ||
330 (!ctx_bss->vif->bss_conf.idle &&
331 !ctx_bss->vif->bss_conf.assoc)) {
332 slot0 = bcnint * 3 - 20;
333 slot1 = 20;
334 } else if (!ctx_pan->vif->bss_conf.idle &&
335 !ctx_pan->vif->bss_conf.assoc) {
336 slot1 = bcnint * 3 - 20;
337 slot0 = 20;
338 }
339 } else if (ctx_pan->vif) {
340 slot0 = 0;
341 slot1 = max_t(int, 1, ctx_pan->vif->bss_conf.dtim_period) *
342 ctx_pan->vif->bss_conf.beacon_int;
343 slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1);
344
345 if (test_bit(STATUS_SCAN_HW, &priv->status)) {
346 slot0 = slot1 * 3 - 20;
347 slot1 = 20;
348 }
349 }
350
351 cmd.slots[0].width = cpu_to_le16(slot0);
352 cmd.slots[1].width = cpu_to_le16(slot1);
353
354 ret = iwl_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, sizeof(cmd), &cmd);
355 if (ret)
356 IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret);
357
358 return ret;
359}
360
269struct iwl_hcmd_ops iwlagn_hcmd = { 361struct iwl_hcmd_ops iwlagn_hcmd = {
270 .rxon_assoc = iwlagn_send_rxon_assoc, 362 .rxon_assoc = iwlagn_send_rxon_assoc,
271 .commit_rxon = iwl_commit_rxon, 363 .commit_rxon = iwlagn_commit_rxon,
272 .set_rxon_chain = iwl_set_rxon_chain, 364 .set_rxon_chain = iwlagn_set_rxon_chain,
273 .set_tx_ant = iwlagn_send_tx_ant_config, 365 .set_tx_ant = iwlagn_send_tx_ant_config,
274 .send_bt_config = iwl_send_bt_config, 366 .send_bt_config = iwl_send_bt_config,
367 .set_pan_params = iwlagn_set_pan_params,
368};
369
370struct iwl_hcmd_ops iwlagn_bt_hcmd = {
371 .rxon_assoc = iwlagn_send_rxon_assoc,
372 .commit_rxon = iwlagn_commit_rxon,
373 .set_rxon_chain = iwlagn_set_rxon_chain,
374 .set_tx_ant = iwlagn_send_tx_ant_config,
375 .send_bt_config = iwlagn_send_advance_bt_config,
376 .set_pan_params = iwlagn_set_pan_params,
275}; 377};
276 378
277struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { 379struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = {
@@ -282,4 +384,5 @@ struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = {
282 .tx_cmd_protection = iwlagn_tx_cmd_protection, 384 .tx_cmd_protection = iwlagn_tx_cmd_protection,
283 .calc_rssi = iwlagn_calc_rssi, 385 .calc_rssi = iwlagn_calc_rssi,
284 .request_scan = iwlagn_request_scan, 386 .request_scan = iwlagn_request_scan,
387 .post_scan = iwlagn_post_scan,
285}; 388};