diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 157 |
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 | ||
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; |
@@ -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 | ||
274 | static 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 | |||
269 | struct iwl_hcmd_ops iwlagn_hcmd = { | 361 | struct 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 | |||
370 | struct 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 | ||
277 | struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { | 379 | struct 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 | }; |