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.c199
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
40int 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
87int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) 40int 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 */
105static u16 iwlagn_get_hcmd_size(u8 cmd_id, u16 len)
106{
107 return len;
108}
109
110static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) 57static 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
212static 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
269struct iwl_hcmd_ops iwlagn_hcmd = { 304struct 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
312struct 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
277struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { 320struct 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};