diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 199 |
1 files changed, 121 insertions, 78 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 75b901b3eb1e..23fa93deae96 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * | 2 | * |
3 | * GPL LICENSE SUMMARY | 3 | * GPL LICENSE SUMMARY |
4 | * | 4 | * |
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of version 2 of the GNU General Public License as | 8 | * it under the terms of version 2 of the GNU General Public License as |
@@ -37,53 +37,6 @@ | |||
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) | ||
41 | { | ||
42 | int ret = 0; | ||
43 | struct iwl5000_rxon_assoc_cmd rxon_assoc; | ||
44 | const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; | ||
45 | const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; | ||
46 | |||
47 | if ((rxon1->flags == rxon2->flags) && | ||
48 | (rxon1->filter_flags == rxon2->filter_flags) && | ||
49 | (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && | ||
50 | (rxon1->ofdm_ht_single_stream_basic_rates == | ||
51 | rxon2->ofdm_ht_single_stream_basic_rates) && | ||
52 | (rxon1->ofdm_ht_dual_stream_basic_rates == | ||
53 | rxon2->ofdm_ht_dual_stream_basic_rates) && | ||
54 | (rxon1->ofdm_ht_triple_stream_basic_rates == | ||
55 | rxon2->ofdm_ht_triple_stream_basic_rates) && | ||
56 | (rxon1->acquisition_data == rxon2->acquisition_data) && | ||
57 | (rxon1->rx_chain == rxon2->rx_chain) && | ||
58 | (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { | ||
59 | IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | rxon_assoc.flags = priv->staging_rxon.flags; | ||
64 | rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; | ||
65 | rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; | ||
66 | rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; | ||
67 | rxon_assoc.reserved1 = 0; | ||
68 | rxon_assoc.reserved2 = 0; | ||
69 | rxon_assoc.reserved3 = 0; | ||
70 | rxon_assoc.ofdm_ht_single_stream_basic_rates = | ||
71 | priv->staging_rxon.ofdm_ht_single_stream_basic_rates; | ||
72 | rxon_assoc.ofdm_ht_dual_stream_basic_rates = | ||
73 | priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; | ||
74 | rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; | ||
75 | rxon_assoc.ofdm_ht_triple_stream_basic_rates = | ||
76 | priv->staging_rxon.ofdm_ht_triple_stream_basic_rates; | ||
77 | rxon_assoc.acquisition_data = priv->staging_rxon.acquisition_data; | ||
78 | |||
79 | ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, | ||
80 | sizeof(rxon_assoc), &rxon_assoc, NULL); | ||
81 | if (ret) | ||
82 | return ret; | ||
83 | |||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) | 40 | int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) |
88 | { | 41 | { |
89 | struct iwl_tx_ant_config_cmd tx_ant_cmd = { | 42 | struct iwl_tx_ant_config_cmd tx_ant_cmd = { |
@@ -101,12 +54,6 @@ int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) | |||
101 | } | 54 | } |
102 | } | 55 | } |
103 | 56 | ||
104 | /* Currently this is the superset of everything */ | ||
105 | static u16 iwlagn_get_hcmd_size(u8 cmd_id, u16 len) | ||
106 | { | ||
107 | return len; | ||
108 | } | ||
109 | |||
110 | static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | 57 | static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) |
111 | { | 58 | { |
112 | u16 size = (u16)sizeof(struct iwl_addsta_cmd); | 59 | u16 size = (u16)sizeof(struct iwl_addsta_cmd); |
@@ -136,7 +83,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv, | |||
136 | continue; | 83 | continue; |
137 | } | 84 | } |
138 | 85 | ||
139 | delta_g = (priv->cfg->chain_noise_scale * | 86 | delta_g = (priv->cfg->base_params->chain_noise_scale * |
140 | ((s32)average_noise[default_chain] - | 87 | ((s32)average_noise[default_chain] - |
141 | (s32)average_noise[i])) / 1500; | 88 | (s32)average_noise[i])) / 1500; |
142 | 89 | ||
@@ -184,7 +131,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) | |||
184 | int ret; | 131 | int ret; |
185 | 132 | ||
186 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && | 133 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && |
187 | iwl_is_associated(priv)) { | 134 | iwl_is_any_associated(priv)) { |
188 | struct iwl_calib_chain_noise_reset_cmd cmd; | 135 | struct iwl_calib_chain_noise_reset_cmd cmd; |
189 | 136 | ||
190 | /* clear data for chain noise calibration algorithm */ | 137 | /* clear data for chain noise calibration algorithm */ |
@@ -216,16 +163,9 @@ static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, | |||
216 | __le16 fc, __le32 *tx_flags) | 163 | __le16 fc, __le32 *tx_flags) |
217 | { | 164 | { |
218 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS || | 165 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS || |
219 | info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | 166 | info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT || |
167 | info->flags & IEEE80211_TX_CTL_AMPDU) | ||
220 | *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; | 168 | *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; |
221 | return; | ||
222 | } | ||
223 | |||
224 | if (priv->cfg->use_rts_for_aggregation && | ||
225 | info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
226 | *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; | ||
227 | return; | ||
228 | } | ||
229 | } | 169 | } |
230 | 170 | ||
231 | /* Calc max signal level (dBm) among 3 possible receivers */ | 171 | /* Calc max signal level (dBm) among 3 possible receivers */ |
@@ -235,13 +175,13 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv, | |||
235 | /* data from PHY/DSP regarding signal strength, etc., | 175 | /* data from PHY/DSP regarding signal strength, etc., |
236 | * contents are always there, not configurable by host | 176 | * contents are always there, not configurable by host |
237 | */ | 177 | */ |
238 | struct iwl5000_non_cfg_phy *ncphy = | 178 | struct iwlagn_non_cfg_phy *ncphy = |
239 | (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf; | 179 | (struct iwlagn_non_cfg_phy *)rx_resp->non_cfg_phy_buf; |
240 | u32 val, rssi_a, rssi_b, rssi_c, max_rssi; | 180 | u32 val, rssi_a, rssi_b, rssi_c, max_rssi; |
241 | u8 agc; | 181 | u8 agc; |
242 | 182 | ||
243 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]); | 183 | 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; | 184 | agc = (val & IWLAGN_OFDM_AGC_MSK) >> IWLAGN_OFDM_AGC_BIT_POS; |
245 | 185 | ||
246 | /* Find max rssi among 3 possible receivers. | 186 | /* Find max rssi among 3 possible receivers. |
247 | * These values are measured by the digital signal processor (DSP). | 187 | * These values are measured by the digital signal processor (DSP). |
@@ -249,11 +189,14 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv, | |||
249 | * if the radio's automatic gain control (AGC) is working right. | 189 | * if the radio's automatic gain control (AGC) is working right. |
250 | * AGC value (see below) will provide the "interesting" info. | 190 | * AGC value (see below) will provide the "interesting" info. |
251 | */ | 191 | */ |
252 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]); | 192 | 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; | 193 | rssi_a = (val & IWLAGN_OFDM_RSSI_INBAND_A_BITMSK) >> |
254 | rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS; | 194 | IWLAGN_OFDM_RSSI_A_BIT_POS; |
255 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]); | 195 | rssi_b = (val & IWLAGN_OFDM_RSSI_INBAND_B_BITMSK) >> |
256 | rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS; | 196 | IWLAGN_OFDM_RSSI_B_BIT_POS; |
197 | val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_C_IDX]); | ||
198 | rssi_c = (val & IWLAGN_OFDM_RSSI_INBAND_C_BITMSK) >> | ||
199 | IWLAGN_OFDM_RSSI_C_BIT_POS; | ||
257 | 200 | ||
258 | max_rssi = max_t(u32, rssi_a, rssi_b); | 201 | max_rssi = max_t(u32, rssi_a, rssi_b); |
259 | max_rssi = max_t(u32, max_rssi, rssi_c); | 202 | max_rssi = max_t(u32, max_rssi, rssi_c); |
@@ -266,20 +209,120 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv, | |||
266 | return max_rssi - agc - IWLAGN_RSSI_OFFSET; | 209 | return max_rssi - agc - IWLAGN_RSSI_OFFSET; |
267 | } | 210 | } |
268 | 211 | ||
212 | static int iwlagn_set_pan_params(struct iwl_priv *priv) | ||
213 | { | ||
214 | struct iwl_wipan_params_cmd cmd; | ||
215 | struct iwl_rxon_context *ctx_bss, *ctx_pan; | ||
216 | int slot0 = 300, slot1 = 0; | ||
217 | int ret; | ||
218 | |||
219 | if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS)) | ||
220 | return 0; | ||
221 | |||
222 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); | ||
223 | |||
224 | lockdep_assert_held(&priv->mutex); | ||
225 | |||
226 | ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
227 | ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN]; | ||
228 | |||
229 | /* | ||
230 | * If the PAN context is inactive, then we don't need | ||
231 | * to update the PAN parameters, the last thing we'll | ||
232 | * have done before it goes inactive is making the PAN | ||
233 | * parameters be WLAN-only. | ||
234 | */ | ||
235 | if (!ctx_pan->is_active) | ||
236 | return 0; | ||
237 | |||
238 | memset(&cmd, 0, sizeof(cmd)); | ||
239 | |||
240 | /* only 2 slots are currently allowed */ | ||
241 | cmd.num_slots = 2; | ||
242 | |||
243 | cmd.slots[0].type = 0; /* BSS */ | ||
244 | cmd.slots[1].type = 1; /* PAN */ | ||
245 | |||
246 | if (priv->_agn.hw_roc_channel) { | ||
247 | /* both contexts must be used for this to happen */ | ||
248 | slot1 = priv->_agn.hw_roc_duration; | ||
249 | slot0 = IWL_MIN_SLOT_TIME; | ||
250 | } else if (ctx_bss->vif && ctx_pan->vif) { | ||
251 | int bcnint = ctx_pan->vif->bss_conf.beacon_int; | ||
252 | int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1; | ||
253 | |||
254 | /* should be set, but seems unused?? */ | ||
255 | cmd.flags |= cpu_to_le16(IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE); | ||
256 | |||
257 | if (ctx_pan->vif->type == NL80211_IFTYPE_AP && | ||
258 | bcnint && | ||
259 | bcnint != ctx_bss->vif->bss_conf.beacon_int) { | ||
260 | IWL_ERR(priv, | ||
261 | "beacon intervals don't match (%d, %d)\n", | ||
262 | ctx_bss->vif->bss_conf.beacon_int, | ||
263 | ctx_pan->vif->bss_conf.beacon_int); | ||
264 | } else | ||
265 | bcnint = max_t(int, bcnint, | ||
266 | ctx_bss->vif->bss_conf.beacon_int); | ||
267 | if (!bcnint) | ||
268 | bcnint = DEFAULT_BEACON_INTERVAL; | ||
269 | slot0 = bcnint / 2; | ||
270 | slot1 = bcnint - slot0; | ||
271 | |||
272 | if (test_bit(STATUS_SCAN_HW, &priv->status) || | ||
273 | (!ctx_bss->vif->bss_conf.idle && | ||
274 | !ctx_bss->vif->bss_conf.assoc)) { | ||
275 | slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME; | ||
276 | slot1 = IWL_MIN_SLOT_TIME; | ||
277 | } else if (!ctx_pan->vif->bss_conf.idle && | ||
278 | !ctx_pan->vif->bss_conf.assoc) { | ||
279 | slot1 = bcnint * 3 - IWL_MIN_SLOT_TIME; | ||
280 | slot0 = IWL_MIN_SLOT_TIME; | ||
281 | } | ||
282 | } else if (ctx_pan->vif) { | ||
283 | slot0 = 0; | ||
284 | slot1 = max_t(int, 1, ctx_pan->vif->bss_conf.dtim_period) * | ||
285 | ctx_pan->vif->bss_conf.beacon_int; | ||
286 | slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1); | ||
287 | |||
288 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | ||
289 | slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME; | ||
290 | slot1 = IWL_MIN_SLOT_TIME; | ||
291 | } | ||
292 | } | ||
293 | |||
294 | cmd.slots[0].width = cpu_to_le16(slot0); | ||
295 | cmd.slots[1].width = cpu_to_le16(slot1); | ||
296 | |||
297 | ret = iwl_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, sizeof(cmd), &cmd); | ||
298 | if (ret) | ||
299 | IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret); | ||
300 | |||
301 | return ret; | ||
302 | } | ||
303 | |||
269 | struct iwl_hcmd_ops iwlagn_hcmd = { | 304 | struct iwl_hcmd_ops iwlagn_hcmd = { |
270 | .rxon_assoc = iwlagn_send_rxon_assoc, | 305 | .commit_rxon = iwlagn_commit_rxon, |
271 | .commit_rxon = iwl_commit_rxon, | 306 | .set_rxon_chain = iwlagn_set_rxon_chain, |
272 | .set_rxon_chain = iwl_set_rxon_chain, | ||
273 | .set_tx_ant = iwlagn_send_tx_ant_config, | 307 | .set_tx_ant = iwlagn_send_tx_ant_config, |
274 | .send_bt_config = iwl_send_bt_config, | 308 | .send_bt_config = iwl_send_bt_config, |
309 | .set_pan_params = iwlagn_set_pan_params, | ||
310 | }; | ||
311 | |||
312 | struct iwl_hcmd_ops iwlagn_bt_hcmd = { | ||
313 | .commit_rxon = iwlagn_commit_rxon, | ||
314 | .set_rxon_chain = iwlagn_set_rxon_chain, | ||
315 | .set_tx_ant = iwlagn_send_tx_ant_config, | ||
316 | .send_bt_config = iwlagn_send_advance_bt_config, | ||
317 | .set_pan_params = iwlagn_set_pan_params, | ||
275 | }; | 318 | }; |
276 | 319 | ||
277 | struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { | 320 | struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { |
278 | .get_hcmd_size = iwlagn_get_hcmd_size, | ||
279 | .build_addsta_hcmd = iwlagn_build_addsta_hcmd, | 321 | .build_addsta_hcmd = iwlagn_build_addsta_hcmd, |
280 | .gain_computation = iwlagn_gain_computation, | 322 | .gain_computation = iwlagn_gain_computation, |
281 | .chain_noise_reset = iwlagn_chain_noise_reset, | 323 | .chain_noise_reset = iwlagn_chain_noise_reset, |
282 | .tx_cmd_protection = iwlagn_tx_cmd_protection, | 324 | .tx_cmd_protection = iwlagn_tx_cmd_protection, |
283 | .calc_rssi = iwlagn_calc_rssi, | 325 | .calc_rssi = iwlagn_calc_rssi, |
284 | .request_scan = iwlagn_request_scan, | 326 | .request_scan = iwlagn_request_scan, |
327 | .post_scan = iwlagn_post_scan, | ||
285 | }; | 328 | }; |