diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 104 |
1 files changed, 90 insertions, 14 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 84fe06adcef..6fb52abafc8 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 | ||
40 | int iwlagn_send_rxon_assoc(struct iwl_priv *priv) | 40 | int 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; |
@@ -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 */ |
@@ -269,12 +270,86 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv, | |||
269 | return max_rssi - agc - IWLAGN_RSSI_OFFSET; | 270 | return max_rssi - agc - IWLAGN_RSSI_OFFSET; |
270 | } | 271 | } |
271 | 272 | ||
273 | static int iwlagn_set_pan_params(struct iwl_priv *priv) | ||
274 | { | ||
275 | struct iwl_wipan_params_cmd cmd; | ||
276 | struct iwl_rxon_context *ctx_bss, *ctx_pan; | ||
277 | int slot0 = 300, slot1 = 0; | ||
278 | int ret; | ||
279 | |||
280 | if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS)) | ||
281 | return 0; | ||
282 | |||
283 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); | ||
284 | |||
285 | lockdep_assert_held(&priv->mutex); | ||
286 | |||
287 | ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
288 | ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN]; | ||
289 | |||
290 | memset(&cmd, 0, sizeof(cmd)); | ||
291 | |||
292 | /* only 2 slots are currently allowed */ | ||
293 | cmd.num_slots = 2; | ||
294 | |||
295 | cmd.slots[0].type = 0; /* BSS */ | ||
296 | cmd.slots[1].type = 1; /* PAN */ | ||
297 | |||
298 | if (ctx_bss->vif && ctx_pan->vif) { | ||
299 | int bcnint = ctx_pan->vif->bss_conf.beacon_int; | ||
300 | |||
301 | /* should be set, but seems unused?? */ | ||
302 | cmd.flags |= cpu_to_le16(IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE); | ||
303 | |||
304 | if (ctx_pan->vif->type == NL80211_IFTYPE_AP && | ||
305 | bcnint && | ||
306 | bcnint != ctx_bss->vif->bss_conf.beacon_int) { | ||
307 | IWL_ERR(priv, | ||
308 | "beacon intervals don't match (%d, %d)\n", | ||
309 | ctx_bss->vif->bss_conf.beacon_int, | ||
310 | ctx_pan->vif->bss_conf.beacon_int); | ||
311 | } else | ||
312 | bcnint = max_t(int, bcnint, | ||
313 | ctx_bss->vif->bss_conf.beacon_int); | ||
314 | if (!bcnint) | ||
315 | bcnint = 100; | ||
316 | slot0 = bcnint / 2; | ||
317 | slot1 = bcnint - slot0; | ||
318 | |||
319 | if (test_bit(STATUS_SCAN_HW, &priv->status) || | ||
320 | (!ctx_bss->vif->bss_conf.idle && | ||
321 | !ctx_bss->vif->bss_conf.assoc)) { | ||
322 | slot0 = bcnint * 3 - 20; | ||
323 | slot1 = 20; | ||
324 | } else if (!ctx_pan->vif->bss_conf.idle && | ||
325 | !ctx_pan->vif->bss_conf.assoc) { | ||
326 | slot1 = bcnint * 3 - 20; | ||
327 | slot0 = 20; | ||
328 | } | ||
329 | } else if (ctx_pan->vif) { | ||
330 | slot0 = 0; | ||
331 | slot1 = max_t(int, 1, ctx_pan->vif->bss_conf.dtim_period) * | ||
332 | ctx_pan->vif->bss_conf.beacon_int; | ||
333 | slot1 = max_t(int, 100, slot1); | ||
334 | } | ||
335 | |||
336 | cmd.slots[0].width = cpu_to_le16(slot0); | ||
337 | cmd.slots[1].width = cpu_to_le16(slot1); | ||
338 | |||
339 | ret = iwl_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, sizeof(cmd), &cmd); | ||
340 | if (ret) | ||
341 | IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret); | ||
342 | |||
343 | return ret; | ||
344 | } | ||
345 | |||
272 | struct iwl_hcmd_ops iwlagn_hcmd = { | 346 | struct iwl_hcmd_ops iwlagn_hcmd = { |
273 | .rxon_assoc = iwlagn_send_rxon_assoc, | 347 | .rxon_assoc = iwlagn_send_rxon_assoc, |
274 | .commit_rxon = iwl_commit_rxon, | 348 | .commit_rxon = iwl_commit_rxon, |
275 | .set_rxon_chain = iwl_set_rxon_chain, | 349 | .set_rxon_chain = iwl_set_rxon_chain, |
276 | .set_tx_ant = iwlagn_send_tx_ant_config, | 350 | .set_tx_ant = iwlagn_send_tx_ant_config, |
277 | .send_bt_config = iwl_send_bt_config, | 351 | .send_bt_config = iwl_send_bt_config, |
352 | .set_pan_params = iwlagn_set_pan_params, | ||
278 | }; | 353 | }; |
279 | 354 | ||
280 | struct iwl_hcmd_ops iwlagn_bt_hcmd = { | 355 | struct iwl_hcmd_ops iwlagn_bt_hcmd = { |
@@ -283,6 +358,7 @@ struct iwl_hcmd_ops iwlagn_bt_hcmd = { | |||
283 | .set_rxon_chain = iwl_set_rxon_chain, | 358 | .set_rxon_chain = iwl_set_rxon_chain, |
284 | .set_tx_ant = iwlagn_send_tx_ant_config, | 359 | .set_tx_ant = iwlagn_send_tx_ant_config, |
285 | .send_bt_config = iwlagn_send_advance_bt_config, | 360 | .send_bt_config = iwlagn_send_advance_bt_config, |
361 | .set_pan_params = iwlagn_set_pan_params, | ||
286 | }; | 362 | }; |
287 | 363 | ||
288 | struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { | 364 | struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { |