aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-4965.c
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2008-04-16 19:34:47 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-05-07 15:02:10 -0400
commitf0832f137c21d130998a0f97f97ac01a2d97210b (patch)
tree6b9af836baa6133caaf4aebe3717719c9cbb7725 /drivers/net/wireless/iwlwifi/iwl-4965.c
parenta7ca0268b5dfffcaa8a1fe40c6eccdeac50fa3ea (diff)
iwlwifi: HW dependent run time calibration
This patch does several things: 1) rename CONFIG_IWL4965_SENSITIVITY to IWL4965_RUN_TIME_CALIB which is better semantic 2) move all the run time calibration to a new file: iwl-calib.c 3) simplify the sensitivity calibration flow and make it HW dependent 4) make the chain noise calibration flow HW dependent Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-4965.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c870
1 files changed, 106 insertions, 764 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 17f629fb96ff..be4cc5ffa742 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -43,6 +43,7 @@
43#include "iwl-core.h" 43#include "iwl-core.h"
44#include "iwl-io.h" 44#include "iwl-io.h"
45#include "iwl-helpers.h" 45#include "iwl-helpers.h"
46#include "iwl-calib.h"
46 47
47/* module parameters */ 48/* module parameters */
48static struct iwl_mod_params iwl4965_mod_params = { 49static struct iwl_mod_params iwl4965_mod_params = {
@@ -1032,418 +1033,15 @@ void iwl4965_rf_kill_ct_config(struct iwl_priv *priv)
1032 IWL_DEBUG_INFO("REPLY_CT_KILL_CONFIG_CMD succeeded\n"); 1033 IWL_DEBUG_INFO("REPLY_CT_KILL_CONFIG_CMD succeeded\n");
1033} 1034}
1034 1035
1035#ifdef CONFIG_IWL4965_SENSITIVITY 1036#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
1036
1037/* "false alarms" are signals that our DSP tries to lock onto,
1038 * but then determines that they are either noise, or transmissions
1039 * from a distant wireless network (also "noise", really) that get
1040 * "stepped on" by stronger transmissions within our own network.
1041 * This algorithm attempts to set a sensitivity level that is high
1042 * enough to receive all of our own network traffic, but not so
1043 * high that our DSP gets too busy trying to lock onto non-network
1044 * activity/noise. */
1045static int iwl4965_sens_energy_cck(struct iwl_priv *priv,
1046 u32 norm_fa,
1047 u32 rx_enable_time,
1048 struct statistics_general_data *rx_info)
1049{
1050 u32 max_nrg_cck = 0;
1051 int i = 0;
1052 u8 max_silence_rssi = 0;
1053 u32 silence_ref = 0;
1054 u8 silence_rssi_a = 0;
1055 u8 silence_rssi_b = 0;
1056 u8 silence_rssi_c = 0;
1057 u32 val;
1058
1059 /* "false_alarms" values below are cross-multiplications to assess the
1060 * numbers of false alarms within the measured period of actual Rx
1061 * (Rx is off when we're txing), vs the min/max expected false alarms
1062 * (some should be expected if rx is sensitive enough) in a
1063 * hypothetical listening period of 200 time units (TU), 204.8 msec:
1064 *
1065 * MIN_FA/fixed-time < false_alarms/actual-rx-time < MAX_FA/beacon-time
1066 *
1067 * */
1068 u32 false_alarms = norm_fa * 200 * 1024;
1069 u32 max_false_alarms = MAX_FA_CCK * rx_enable_time;
1070 u32 min_false_alarms = MIN_FA_CCK * rx_enable_time;
1071 struct iwl4965_sensitivity_data *data = NULL;
1072
1073 data = &(priv->sensitivity_data);
1074
1075 data->nrg_auto_corr_silence_diff = 0;
1076
1077 /* Find max silence rssi among all 3 receivers.
1078 * This is background noise, which may include transmissions from other
1079 * networks, measured during silence before our network's beacon */
1080 silence_rssi_a = (u8)((rx_info->beacon_silence_rssi_a &
1081 ALL_BAND_FILTER) >> 8);
1082 silence_rssi_b = (u8)((rx_info->beacon_silence_rssi_b &
1083 ALL_BAND_FILTER) >> 8);
1084 silence_rssi_c = (u8)((rx_info->beacon_silence_rssi_c &
1085 ALL_BAND_FILTER) >> 8);
1086
1087 val = max(silence_rssi_b, silence_rssi_c);
1088 max_silence_rssi = max(silence_rssi_a, (u8) val);
1089
1090 /* Store silence rssi in 20-beacon history table */
1091 data->nrg_silence_rssi[data->nrg_silence_idx] = max_silence_rssi;
1092 data->nrg_silence_idx++;
1093 if (data->nrg_silence_idx >= NRG_NUM_PREV_STAT_L)
1094 data->nrg_silence_idx = 0;
1095
1096 /* Find max silence rssi across 20 beacon history */
1097 for (i = 0; i < NRG_NUM_PREV_STAT_L; i++) {
1098 val = data->nrg_silence_rssi[i];
1099 silence_ref = max(silence_ref, val);
1100 }
1101 IWL_DEBUG_CALIB("silence a %u, b %u, c %u, 20-bcn max %u\n",
1102 silence_rssi_a, silence_rssi_b, silence_rssi_c,
1103 silence_ref);
1104
1105 /* Find max rx energy (min value!) among all 3 receivers,
1106 * measured during beacon frame.
1107 * Save it in 10-beacon history table. */
1108 i = data->nrg_energy_idx;
1109 val = min(rx_info->beacon_energy_b, rx_info->beacon_energy_c);
1110 data->nrg_value[i] = min(rx_info->beacon_energy_a, val);
1111
1112 data->nrg_energy_idx++;
1113 if (data->nrg_energy_idx >= 10)
1114 data->nrg_energy_idx = 0;
1115
1116 /* Find min rx energy (max value) across 10 beacon history.
1117 * This is the minimum signal level that we want to receive well.
1118 * Add backoff (margin so we don't miss slightly lower energy frames).
1119 * This establishes an upper bound (min value) for energy threshold. */
1120 max_nrg_cck = data->nrg_value[0];
1121 for (i = 1; i < 10; i++)
1122 max_nrg_cck = (u32) max(max_nrg_cck, (data->nrg_value[i]));
1123 max_nrg_cck += 6;
1124
1125 IWL_DEBUG_CALIB("rx energy a %u, b %u, c %u, 10-bcn max/min %u\n",
1126 rx_info->beacon_energy_a, rx_info->beacon_energy_b,
1127 rx_info->beacon_energy_c, max_nrg_cck - 6);
1128
1129 /* Count number of consecutive beacons with fewer-than-desired
1130 * false alarms. */
1131 if (false_alarms < min_false_alarms)
1132 data->num_in_cck_no_fa++;
1133 else
1134 data->num_in_cck_no_fa = 0;
1135 IWL_DEBUG_CALIB("consecutive bcns with few false alarms = %u\n",
1136 data->num_in_cck_no_fa);
1137
1138 /* If we got too many false alarms this time, reduce sensitivity */
1139 if (false_alarms > max_false_alarms) {
1140 IWL_DEBUG_CALIB("norm FA %u > max FA %u\n",
1141 false_alarms, max_false_alarms);
1142 IWL_DEBUG_CALIB("... reducing sensitivity\n");
1143 data->nrg_curr_state = IWL_FA_TOO_MANY;
1144
1145 if (data->auto_corr_cck > AUTO_CORR_MAX_TH_CCK) {
1146 /* Store for "fewer than desired" on later beacon */
1147 data->nrg_silence_ref = silence_ref;
1148
1149 /* increase energy threshold (reduce nrg value)
1150 * to decrease sensitivity */
1151 if (data->nrg_th_cck > (NRG_MAX_CCK + NRG_STEP_CCK))
1152 data->nrg_th_cck = data->nrg_th_cck
1153 - NRG_STEP_CCK;
1154 }
1155
1156 /* increase auto_corr values to decrease sensitivity */
1157 if (data->auto_corr_cck < AUTO_CORR_MAX_TH_CCK)
1158 data->auto_corr_cck = AUTO_CORR_MAX_TH_CCK + 1;
1159 else {
1160 val = data->auto_corr_cck + AUTO_CORR_STEP_CCK;
1161 data->auto_corr_cck = min((u32)AUTO_CORR_MAX_CCK, val);
1162 }
1163 val = data->auto_corr_cck_mrc + AUTO_CORR_STEP_CCK;
1164 data->auto_corr_cck_mrc = min((u32)AUTO_CORR_MAX_CCK_MRC, val);
1165
1166 /* Else if we got fewer than desired, increase sensitivity */
1167 } else if (false_alarms < min_false_alarms) {
1168 data->nrg_curr_state = IWL_FA_TOO_FEW;
1169
1170 /* Compare silence level with silence level for most recent
1171 * healthy number or too many false alarms */
1172 data->nrg_auto_corr_silence_diff = (s32)data->nrg_silence_ref -
1173 (s32)silence_ref;
1174
1175 IWL_DEBUG_CALIB("norm FA %u < min FA %u, silence diff %d\n",
1176 false_alarms, min_false_alarms,
1177 data->nrg_auto_corr_silence_diff);
1178
1179 /* Increase value to increase sensitivity, but only if:
1180 * 1a) previous beacon did *not* have *too many* false alarms
1181 * 1b) AND there's a significant difference in Rx levels
1182 * from a previous beacon with too many, or healthy # FAs
1183 * OR 2) We've seen a lot of beacons (100) with too few
1184 * false alarms */
1185 if ((data->nrg_prev_state != IWL_FA_TOO_MANY) &&
1186 ((data->nrg_auto_corr_silence_diff > NRG_DIFF) ||
1187 (data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA))) {
1188
1189 IWL_DEBUG_CALIB("... increasing sensitivity\n");
1190 /* Increase nrg value to increase sensitivity */
1191 val = data->nrg_th_cck + NRG_STEP_CCK;
1192 data->nrg_th_cck = min((u32)NRG_MIN_CCK, val);
1193
1194 /* Decrease auto_corr values to increase sensitivity */
1195 val = data->auto_corr_cck - AUTO_CORR_STEP_CCK;
1196 data->auto_corr_cck = max((u32)AUTO_CORR_MIN_CCK, val);
1197
1198 val = data->auto_corr_cck_mrc - AUTO_CORR_STEP_CCK;
1199 data->auto_corr_cck_mrc =
1200 max((u32)AUTO_CORR_MIN_CCK_MRC, val);
1201
1202 } else
1203 IWL_DEBUG_CALIB("... but not changing sensitivity\n");
1204
1205 /* Else we got a healthy number of false alarms, keep status quo */
1206 } else {
1207 IWL_DEBUG_CALIB(" FA in safe zone\n");
1208 data->nrg_curr_state = IWL_FA_GOOD_RANGE;
1209
1210 /* Store for use in "fewer than desired" with later beacon */
1211 data->nrg_silence_ref = silence_ref;
1212
1213 /* If previous beacon had too many false alarms,
1214 * give it some extra margin by reducing sensitivity again
1215 * (but don't go below measured energy of desired Rx) */
1216 if (IWL_FA_TOO_MANY == data->nrg_prev_state) {
1217 IWL_DEBUG_CALIB("... increasing margin\n");
1218 data->nrg_th_cck -= NRG_MARGIN;
1219 }
1220 }
1221
1222 /* Make sure the energy threshold does not go above the measured
1223 * energy of the desired Rx signals (reduced by backoff margin),
1224 * or else we might start missing Rx frames.
1225 * Lower value is higher energy, so we use max()!
1226 */
1227 data->nrg_th_cck = max(max_nrg_cck, data->nrg_th_cck);
1228 IWL_DEBUG_CALIB("new nrg_th_cck %u\n", data->nrg_th_cck);
1229
1230 data->nrg_prev_state = data->nrg_curr_state;
1231
1232 return 0;
1233}
1234
1235
1236static int iwl4965_sens_auto_corr_ofdm(struct iwl_priv *priv,
1237 u32 norm_fa,
1238 u32 rx_enable_time)
1239{
1240 u32 val;
1241 u32 false_alarms = norm_fa * 200 * 1024;
1242 u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time;
1243 u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time;
1244 struct iwl4965_sensitivity_data *data = NULL;
1245
1246 data = &(priv->sensitivity_data);
1247
1248 /* If we got too many false alarms this time, reduce sensitivity */
1249 if (false_alarms > max_false_alarms) {
1250
1251 IWL_DEBUG_CALIB("norm FA %u > max FA %u)\n",
1252 false_alarms, max_false_alarms);
1253
1254 val = data->auto_corr_ofdm + AUTO_CORR_STEP_OFDM;
1255 data->auto_corr_ofdm =
1256 min((u32)AUTO_CORR_MAX_OFDM, val);
1257
1258 val = data->auto_corr_ofdm_mrc + AUTO_CORR_STEP_OFDM;
1259 data->auto_corr_ofdm_mrc =
1260 min((u32)AUTO_CORR_MAX_OFDM_MRC, val);
1261
1262 val = data->auto_corr_ofdm_x1 + AUTO_CORR_STEP_OFDM;
1263 data->auto_corr_ofdm_x1 =
1264 min((u32)AUTO_CORR_MAX_OFDM_X1, val);
1265
1266 val = data->auto_corr_ofdm_mrc_x1 + AUTO_CORR_STEP_OFDM;
1267 data->auto_corr_ofdm_mrc_x1 =
1268 min((u32)AUTO_CORR_MAX_OFDM_MRC_X1, val);
1269 }
1270
1271 /* Else if we got fewer than desired, increase sensitivity */
1272 else if (false_alarms < min_false_alarms) {
1273
1274 IWL_DEBUG_CALIB("norm FA %u < min FA %u\n",
1275 false_alarms, min_false_alarms);
1276
1277 val = data->auto_corr_ofdm - AUTO_CORR_STEP_OFDM;
1278 data->auto_corr_ofdm =
1279 max((u32)AUTO_CORR_MIN_OFDM, val);
1280
1281 val = data->auto_corr_ofdm_mrc - AUTO_CORR_STEP_OFDM;
1282 data->auto_corr_ofdm_mrc =
1283 max((u32)AUTO_CORR_MIN_OFDM_MRC, val);
1284
1285 val = data->auto_corr_ofdm_x1 - AUTO_CORR_STEP_OFDM;
1286 data->auto_corr_ofdm_x1 =
1287 max((u32)AUTO_CORR_MIN_OFDM_X1, val);
1288
1289 val = data->auto_corr_ofdm_mrc_x1 - AUTO_CORR_STEP_OFDM;
1290 data->auto_corr_ofdm_mrc_x1 =
1291 max((u32)AUTO_CORR_MIN_OFDM_MRC_X1, val);
1292 }
1293
1294 else
1295 IWL_DEBUG_CALIB("min FA %u < norm FA %u < max FA %u OK\n",
1296 min_false_alarms, false_alarms, max_false_alarms);
1297
1298 return 0;
1299}
1300
1301static int iwl4965_sensitivity_callback(struct iwl_priv *priv,
1302 struct iwl_cmd *cmd, struct sk_buff *skb)
1303{
1304 /* We didn't cache the SKB; let the caller free it */
1305 return 1;
1306}
1307
1308/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
1309static int iwl4965_sensitivity_write(struct iwl_priv *priv, u8 flags)
1310{
1311 struct iwl4965_sensitivity_cmd cmd ;
1312 struct iwl4965_sensitivity_data *data = NULL;
1313 struct iwl_host_cmd cmd_out = {
1314 .id = SENSITIVITY_CMD,
1315 .len = sizeof(struct iwl4965_sensitivity_cmd),
1316 .meta.flags = flags,
1317 .data = &cmd,
1318 };
1319 int ret;
1320
1321 data = &(priv->sensitivity_data);
1322
1323 memset(&cmd, 0, sizeof(cmd));
1324
1325 cmd.table[HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX] =
1326 cpu_to_le16((u16)data->auto_corr_ofdm);
1327 cmd.table[HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX] =
1328 cpu_to_le16((u16)data->auto_corr_ofdm_mrc);
1329 cmd.table[HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX] =
1330 cpu_to_le16((u16)data->auto_corr_ofdm_x1);
1331 cmd.table[HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX] =
1332 cpu_to_le16((u16)data->auto_corr_ofdm_mrc_x1);
1333
1334 cmd.table[HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX] =
1335 cpu_to_le16((u16)data->auto_corr_cck);
1336 cmd.table[HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX] =
1337 cpu_to_le16((u16)data->auto_corr_cck_mrc);
1338
1339 cmd.table[HD_MIN_ENERGY_CCK_DET_INDEX] =
1340 cpu_to_le16((u16)data->nrg_th_cck);
1341 cmd.table[HD_MIN_ENERGY_OFDM_DET_INDEX] =
1342 cpu_to_le16((u16)data->nrg_th_ofdm);
1343
1344 cmd.table[HD_BARKER_CORR_TH_ADD_MIN_INDEX] =
1345 __constant_cpu_to_le16(190);
1346 cmd.table[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] =
1347 __constant_cpu_to_le16(390);
1348 cmd.table[HD_OFDM_ENERGY_TH_IN_INDEX] =
1349 __constant_cpu_to_le16(62);
1350
1351 IWL_DEBUG_CALIB("ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n",
1352 data->auto_corr_ofdm, data->auto_corr_ofdm_mrc,
1353 data->auto_corr_ofdm_x1, data->auto_corr_ofdm_mrc_x1,
1354 data->nrg_th_ofdm);
1355
1356 IWL_DEBUG_CALIB("cck: ac %u mrc %u thresh %u\n",
1357 data->auto_corr_cck, data->auto_corr_cck_mrc,
1358 data->nrg_th_cck);
1359
1360 /* Update uCode's "work" table, and copy it to DSP */
1361 cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE;
1362
1363 if (flags & CMD_ASYNC)
1364 cmd_out.meta.u.callback = iwl4965_sensitivity_callback;
1365
1366 /* Don't send command to uCode if nothing has changed */
1367 if (!memcmp(&cmd.table[0], &(priv->sensitivity_tbl[0]),
1368 sizeof(u16)*HD_TABLE_SIZE)) {
1369 IWL_DEBUG_CALIB("No change in SENSITIVITY_CMD\n");
1370 return 0;
1371 }
1372
1373 /* Copy table for comparison next time */
1374 memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
1375 sizeof(u16)*HD_TABLE_SIZE);
1376
1377 ret = iwl_send_cmd(priv, &cmd_out);
1378 if (ret)
1379 IWL_ERROR("SENSITIVITY_CMD failed\n");
1380
1381 return ret;
1382}
1383
1384void iwl4965_init_sensitivity(struct iwl_priv *priv, u8 flags, u8 force)
1385{
1386 struct iwl4965_sensitivity_data *data = NULL;
1387 int i;
1388 int ret = 0;
1389
1390 IWL_DEBUG_CALIB("Start iwl4965_init_sensitivity\n");
1391
1392 if (force)
1393 memset(&(priv->sensitivity_tbl[0]), 0,
1394 sizeof(u16)*HD_TABLE_SIZE);
1395
1396 /* Clear driver's sensitivity algo data */
1397 data = &(priv->sensitivity_data);
1398 memset(data, 0, sizeof(struct iwl4965_sensitivity_data));
1399
1400 data->num_in_cck_no_fa = 0;
1401 data->nrg_curr_state = IWL_FA_TOO_MANY;
1402 data->nrg_prev_state = IWL_FA_TOO_MANY;
1403 data->nrg_silence_ref = 0;
1404 data->nrg_silence_idx = 0;
1405 data->nrg_energy_idx = 0;
1406
1407 for (i = 0; i < 10; i++)
1408 data->nrg_value[i] = 0;
1409
1410 for (i = 0; i < NRG_NUM_PREV_STAT_L; i++)
1411 data->nrg_silence_rssi[i] = 0;
1412
1413 data->auto_corr_ofdm = 90;
1414 data->auto_corr_ofdm_mrc = 170;
1415 data->auto_corr_ofdm_x1 = 105;
1416 data->auto_corr_ofdm_mrc_x1 = 220;
1417 data->auto_corr_cck = AUTO_CORR_CCK_MIN_VAL_DEF;
1418 data->auto_corr_cck_mrc = 200;
1419 data->nrg_th_cck = 100;
1420 data->nrg_th_ofdm = 100;
1421
1422 data->last_bad_plcp_cnt_ofdm = 0;
1423 data->last_fa_cnt_ofdm = 0;
1424 data->last_bad_plcp_cnt_cck = 0;
1425 data->last_fa_cnt_cck = 0;
1426
1427 /* Clear prior Sensitivity command data to force send to uCode */
1428 if (force)
1429 memset(&(priv->sensitivity_tbl[0]), 0,
1430 sizeof(u16)*HD_TABLE_SIZE);
1431
1432 ret |= iwl4965_sensitivity_write(priv, flags);
1433 IWL_DEBUG_CALIB("<<return 0x%X\n", ret);
1434
1435 return;
1436}
1437
1438 1037
1439/* Reset differential Rx gains in NIC to prepare for chain noise calibration. 1038/* Reset differential Rx gains in NIC to prepare for chain noise calibration.
1440 * Called after every association, but this runs only once! 1039 * Called after every association, but this runs only once!
1441 * ... once chain noise is calibrated the first time, it's good forever. */ 1040 * ... once chain noise is calibrated the first time, it's good forever. */
1442void iwl4965_chain_noise_reset(struct iwl_priv *priv) 1041static void iwl4965_chain_noise_reset(struct iwl_priv *priv)
1443{ 1042{
1444 struct iwl4965_chain_noise_data *data = NULL; 1043 struct iwl_chain_noise_data *data = &(priv->chain_noise_data);
1445 1044
1446 data = &(priv->chain_noise_data);
1447 if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { 1045 if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) {
1448 struct iwl4965_calibration_cmd cmd; 1046 struct iwl4965_calibration_cmd cmd;
1449 1047
@@ -1452,357 +1050,76 @@ void iwl4965_chain_noise_reset(struct iwl_priv *priv)
1452 cmd.diff_gain_a = 0; 1050 cmd.diff_gain_a = 0;
1453 cmd.diff_gain_b = 0; 1051 cmd.diff_gain_b = 0;
1454 cmd.diff_gain_c = 0; 1052 cmd.diff_gain_c = 0;
1455 iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD, 1053 if (iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
1456 sizeof(cmd), &cmd, NULL); 1054 sizeof(cmd), &cmd))
1457 msleep(4); 1055 IWL_ERROR("Could not send REPLY_PHY_CALIBRATION_CMD\n");
1458 data->state = IWL_CHAIN_NOISE_ACCUMULATE; 1056 data->state = IWL_CHAIN_NOISE_ACCUMULATE;
1459 IWL_DEBUG_CALIB("Run chain_noise_calibrate\n"); 1057 IWL_DEBUG_CALIB("Run chain_noise_calibrate\n");
1460 } 1058 }
1461 return;
1462} 1059}
1463 1060
1464/* 1061static void iwl4965_gain_computation(struct iwl_priv *priv,
1465 * Accumulate 20 beacons of signal and noise statistics for each of 1062 u32 *average_noise,
1466 * 3 receivers/antennas/rx-chains, then figure out: 1063 u16 min_average_noise_antenna_i,
1467 * 1) Which antennas are connected. 1064 u32 min_average_noise)
1468 * 2) Differential rx gain settings to balance the 3 receivers.
1469 */
1470static void iwl4965_noise_calibration(struct iwl_priv *priv,
1471 struct iwl4965_notif_statistics *stat_resp)
1472{ 1065{
1473 struct iwl4965_chain_noise_data *data = NULL; 1066 int i, ret;
1474 int ret = 0; 1067 struct iwl_chain_noise_data *data = &priv->chain_noise_data;
1475
1476 u32 chain_noise_a;
1477 u32 chain_noise_b;
1478 u32 chain_noise_c;
1479 u32 chain_sig_a;
1480 u32 chain_sig_b;
1481 u32 chain_sig_c;
1482 u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
1483 u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
1484 u32 max_average_sig;
1485 u16 max_average_sig_antenna_i;
1486 u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE;
1487 u16 min_average_noise_antenna_i = INITIALIZATION_VALUE;
1488 u16 i = 0;
1489 u16 chan_num = INITIALIZATION_VALUE;
1490 u32 band = INITIALIZATION_VALUE;
1491 u32 active_chains = 0;
1492 unsigned long flags;
1493 struct statistics_rx_non_phy *rx_info = &(stat_resp->rx.general);
1494
1495 data = &(priv->chain_noise_data);
1496 1068
1497 /* Accumulate just the first 20 beacons after the first association, 1069 data->delta_gain_code[min_average_noise_antenna_i] = 0;
1498 * then we're done forever. */
1499 if (data->state != IWL_CHAIN_NOISE_ACCUMULATE) {
1500 if (data->state == IWL_CHAIN_NOISE_ALIVE)
1501 IWL_DEBUG_CALIB("Wait for noise calib reset\n");
1502 return;
1503 }
1504
1505 spin_lock_irqsave(&priv->lock, flags);
1506 if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
1507 IWL_DEBUG_CALIB(" << Interference data unavailable\n");
1508 spin_unlock_irqrestore(&priv->lock, flags);
1509 return;
1510 }
1511
1512 band = (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) ? 0 : 1;
1513 chan_num = le16_to_cpu(priv->staging_rxon.channel);
1514
1515 /* Make sure we accumulate data for just the associated channel
1516 * (even if scanning). */
1517 if ((chan_num != (le32_to_cpu(stat_resp->flag) >> 16)) ||
1518 ((STATISTICS_REPLY_FLG_BAND_24G_MSK ==
1519 (stat_resp->flag & STATISTICS_REPLY_FLG_BAND_24G_MSK)) && band)) {
1520 IWL_DEBUG_CALIB("Stats not from chan=%d, band=%d\n",
1521 chan_num, band);
1522 spin_unlock_irqrestore(&priv->lock, flags);
1523 return;
1524 }
1525
1526 /* Accumulate beacon statistics values across 20 beacons */
1527 chain_noise_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) &
1528 IN_BAND_FILTER;
1529 chain_noise_b = le32_to_cpu(rx_info->beacon_silence_rssi_b) &
1530 IN_BAND_FILTER;
1531 chain_noise_c = le32_to_cpu(rx_info->beacon_silence_rssi_c) &
1532 IN_BAND_FILTER;
1533
1534 chain_sig_a = le32_to_cpu(rx_info->beacon_rssi_a) & IN_BAND_FILTER;
1535 chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER;
1536 chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER;
1537 1070
1538 spin_unlock_irqrestore(&priv->lock, flags); 1071 for (i = 0; i < NUM_RX_CHAINS; i++) {
1072 s32 delta_g = 0;
1539 1073
1540 data->beacon_count++; 1074 if (!(data->disconn_array[i]) &&
1541 1075 (data->delta_gain_code[i] ==
1542 data->chain_noise_a = (chain_noise_a + data->chain_noise_a);
1543 data->chain_noise_b = (chain_noise_b + data->chain_noise_b);
1544 data->chain_noise_c = (chain_noise_c + data->chain_noise_c);
1545
1546 data->chain_signal_a = (chain_sig_a + data->chain_signal_a);
1547 data->chain_signal_b = (chain_sig_b + data->chain_signal_b);
1548 data->chain_signal_c = (chain_sig_c + data->chain_signal_c);
1549
1550 IWL_DEBUG_CALIB("chan=%d, band=%d, beacon=%d\n", chan_num, band,
1551 data->beacon_count);
1552 IWL_DEBUG_CALIB("chain_sig: a %d b %d c %d\n",
1553 chain_sig_a, chain_sig_b, chain_sig_c);
1554 IWL_DEBUG_CALIB("chain_noise: a %d b %d c %d\n",
1555 chain_noise_a, chain_noise_b, chain_noise_c);
1556
1557 /* If this is the 20th beacon, determine:
1558 * 1) Disconnected antennas (using signal strengths)
1559 * 2) Differential gain (using silence noise) to balance receivers */
1560 if (data->beacon_count == CAL_NUM_OF_BEACONS) {
1561
1562 /* Analyze signal for disconnected antenna */
1563 average_sig[0] = (data->chain_signal_a) / CAL_NUM_OF_BEACONS;
1564 average_sig[1] = (data->chain_signal_b) / CAL_NUM_OF_BEACONS;
1565 average_sig[2] = (data->chain_signal_c) / CAL_NUM_OF_BEACONS;
1566
1567 if (average_sig[0] >= average_sig[1]) {
1568 max_average_sig = average_sig[0];
1569 max_average_sig_antenna_i = 0;
1570 active_chains = (1 << max_average_sig_antenna_i);
1571 } else {
1572 max_average_sig = average_sig[1];
1573 max_average_sig_antenna_i = 1;
1574 active_chains = (1 << max_average_sig_antenna_i);
1575 }
1576
1577 if (average_sig[2] >= max_average_sig) {
1578 max_average_sig = average_sig[2];
1579 max_average_sig_antenna_i = 2;
1580 active_chains = (1 << max_average_sig_antenna_i);
1581 }
1582
1583 IWL_DEBUG_CALIB("average_sig: a %d b %d c %d\n",
1584 average_sig[0], average_sig[1], average_sig[2]);
1585 IWL_DEBUG_CALIB("max_average_sig = %d, antenna %d\n",
1586 max_average_sig, max_average_sig_antenna_i);
1587
1588 /* Compare signal strengths for all 3 receivers. */
1589 for (i = 0; i < NUM_RX_CHAINS; i++) {
1590 if (i != max_average_sig_antenna_i) {
1591 s32 rssi_delta = (max_average_sig -
1592 average_sig[i]);
1593
1594 /* If signal is very weak, compared with
1595 * strongest, mark it as disconnected. */
1596 if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS)
1597 data->disconn_array[i] = 1;
1598 else
1599 active_chains |= (1 << i);
1600 IWL_DEBUG_CALIB("i = %d rssiDelta = %d "
1601 "disconn_array[i] = %d\n",
1602 i, rssi_delta, data->disconn_array[i]);
1603 }
1604 }
1605
1606 /*If both chains A & B are disconnected -
1607 * connect B and leave A as is */
1608 if (data->disconn_array[CHAIN_A] &&
1609 data->disconn_array[CHAIN_B]) {
1610 data->disconn_array[CHAIN_B] = 0;
1611 active_chains |= (1 << CHAIN_B);
1612 IWL_DEBUG_CALIB("both A & B chains are disconnected! "
1613 "W/A - declare B as connected\n");
1614 }
1615
1616 IWL_DEBUG_CALIB("active_chains (bitwise) = 0x%x\n",
1617 active_chains);
1618
1619 /* Save for use within RXON, TX, SCAN commands, etc. */
1620 priv->valid_antenna = active_chains;
1621
1622 /* Analyze noise for rx balance */
1623 average_noise[0] = ((data->chain_noise_a)/CAL_NUM_OF_BEACONS);
1624 average_noise[1] = ((data->chain_noise_b)/CAL_NUM_OF_BEACONS);
1625 average_noise[2] = ((data->chain_noise_c)/CAL_NUM_OF_BEACONS);
1626
1627 for (i = 0; i < NUM_RX_CHAINS; i++) {
1628 if (!(data->disconn_array[i]) &&
1629 (average_noise[i] <= min_average_noise)) {
1630 /* This means that chain i is active and has
1631 * lower noise values so far: */
1632 min_average_noise = average_noise[i];
1633 min_average_noise_antenna_i = i;
1634 }
1635 }
1636
1637 data->delta_gain_code[min_average_noise_antenna_i] = 0;
1638
1639 IWL_DEBUG_CALIB("average_noise: a %d b %d c %d\n",
1640 average_noise[0], average_noise[1],
1641 average_noise[2]);
1642
1643 IWL_DEBUG_CALIB("min_average_noise = %d, antenna %d\n",
1644 min_average_noise, min_average_noise_antenna_i);
1645
1646 for (i = 0; i < NUM_RX_CHAINS; i++) {
1647 s32 delta_g = 0;
1648
1649 if (!(data->disconn_array[i]) &&
1650 (data->delta_gain_code[i] ==
1651 CHAIN_NOISE_DELTA_GAIN_INIT_VAL)) { 1076 CHAIN_NOISE_DELTA_GAIN_INIT_VAL)) {
1652 delta_g = average_noise[i] - min_average_noise; 1077 delta_g = average_noise[i] - min_average_noise;
1653 data->delta_gain_code[i] = (u8)((delta_g * 1078 data->delta_gain_code[i] = (u8)((delta_g * 10) / 15);
1654 10) / 15); 1079 data->delta_gain_code[i] =
1655 if (CHAIN_NOISE_MAX_DELTA_GAIN_CODE < 1080 min(data->delta_gain_code[i],
1656 data->delta_gain_code[i]) 1081 (u8) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
1657 data->delta_gain_code[i] = 1082
1658 CHAIN_NOISE_MAX_DELTA_GAIN_CODE; 1083 data->delta_gain_code[i] =
1659 1084 (data->delta_gain_code[i] | (1 << 2));
1660 data->delta_gain_code[i] = 1085 } else {
1661 (data->delta_gain_code[i] | (1 << 2)); 1086 data->delta_gain_code[i] = 0;
1662 } else
1663 data->delta_gain_code[i] = 0;
1664 }
1665 IWL_DEBUG_CALIB("delta_gain_codes: a %d b %d c %d\n",
1666 data->delta_gain_code[0],
1667 data->delta_gain_code[1],
1668 data->delta_gain_code[2]);
1669
1670 /* Differential gain gets sent to uCode only once */
1671 if (!data->radio_write) {
1672 struct iwl4965_calibration_cmd cmd;
1673 data->radio_write = 1;
1674
1675 memset(&cmd, 0, sizeof(cmd));
1676 cmd.opCode = PHY_CALIBRATE_DIFF_GAIN_CMD;
1677 cmd.diff_gain_a = data->delta_gain_code[0];
1678 cmd.diff_gain_b = data->delta_gain_code[1];
1679 cmd.diff_gain_c = data->delta_gain_code[2];
1680 ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
1681 sizeof(cmd), &cmd);
1682 if (ret)
1683 IWL_DEBUG_CALIB("fail sending cmd "
1684 "REPLY_PHY_CALIBRATION_CMD \n");
1685
1686 /* TODO we might want recalculate
1687 * rx_chain in rxon cmd */
1688
1689 /* Mark so we run this algo only once! */
1690 data->state = IWL_CHAIN_NOISE_CALIBRATED;
1691 } 1087 }
1692 data->chain_noise_a = 0;
1693 data->chain_noise_b = 0;
1694 data->chain_noise_c = 0;
1695 data->chain_signal_a = 0;
1696 data->chain_signal_b = 0;
1697 data->chain_signal_c = 0;
1698 data->beacon_count = 0;
1699 }
1700 return;
1701}
1702
1703static void iwl4965_sensitivity_calibration(struct iwl_priv *priv,
1704 struct iwl4965_notif_statistics *resp)
1705{
1706 u32 rx_enable_time;
1707 u32 fa_cck;
1708 u32 fa_ofdm;
1709 u32 bad_plcp_cck;
1710 u32 bad_plcp_ofdm;
1711 u32 norm_fa_ofdm;
1712 u32 norm_fa_cck;
1713 struct iwl4965_sensitivity_data *data = NULL;
1714 struct statistics_rx_non_phy *rx_info = &(resp->rx.general);
1715 struct statistics_rx *statistics = &(resp->rx);
1716 unsigned long flags;
1717 struct statistics_general_data statis;
1718 int ret;
1719
1720 data = &(priv->sensitivity_data);
1721
1722 if (!iwl_is_associated(priv)) {
1723 IWL_DEBUG_CALIB("<< - not associated\n");
1724 return;
1725 }
1726
1727 spin_lock_irqsave(&priv->lock, flags);
1728 if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
1729 IWL_DEBUG_CALIB("<< invalid data.\n");
1730 spin_unlock_irqrestore(&priv->lock, flags);
1731 return;
1732 }
1733
1734 /* Extract Statistics: */
1735 rx_enable_time = le32_to_cpu(rx_info->channel_load);
1736 fa_cck = le32_to_cpu(statistics->cck.false_alarm_cnt);
1737 fa_ofdm = le32_to_cpu(statistics->ofdm.false_alarm_cnt);
1738 bad_plcp_cck = le32_to_cpu(statistics->cck.plcp_err);
1739 bad_plcp_ofdm = le32_to_cpu(statistics->ofdm.plcp_err);
1740
1741 statis.beacon_silence_rssi_a =
1742 le32_to_cpu(statistics->general.beacon_silence_rssi_a);
1743 statis.beacon_silence_rssi_b =
1744 le32_to_cpu(statistics->general.beacon_silence_rssi_b);
1745 statis.beacon_silence_rssi_c =
1746 le32_to_cpu(statistics->general.beacon_silence_rssi_c);
1747 statis.beacon_energy_a =
1748 le32_to_cpu(statistics->general.beacon_energy_a);
1749 statis.beacon_energy_b =
1750 le32_to_cpu(statistics->general.beacon_energy_b);
1751 statis.beacon_energy_c =
1752 le32_to_cpu(statistics->general.beacon_energy_c);
1753
1754 spin_unlock_irqrestore(&priv->lock, flags);
1755
1756 IWL_DEBUG_CALIB("rx_enable_time = %u usecs\n", rx_enable_time);
1757
1758 if (!rx_enable_time) {
1759 IWL_DEBUG_CALIB("<< RX Enable Time == 0! \n");
1760 return;
1761 }
1762
1763 /* These statistics increase monotonically, and do not reset
1764 * at each beacon. Calculate difference from last value, or just
1765 * use the new statistics value if it has reset or wrapped around. */
1766 if (data->last_bad_plcp_cnt_cck > bad_plcp_cck)
1767 data->last_bad_plcp_cnt_cck = bad_plcp_cck;
1768 else {
1769 bad_plcp_cck -= data->last_bad_plcp_cnt_cck;
1770 data->last_bad_plcp_cnt_cck += bad_plcp_cck;
1771 }
1772
1773 if (data->last_bad_plcp_cnt_ofdm > bad_plcp_ofdm)
1774 data->last_bad_plcp_cnt_ofdm = bad_plcp_ofdm;
1775 else {
1776 bad_plcp_ofdm -= data->last_bad_plcp_cnt_ofdm;
1777 data->last_bad_plcp_cnt_ofdm += bad_plcp_ofdm;
1778 } 1088 }
1089 IWL_DEBUG_CALIB("delta_gain_codes: a %d b %d c %d\n",
1090 data->delta_gain_code[0],
1091 data->delta_gain_code[1],
1092 data->delta_gain_code[2]);
1779 1093
1780 if (data->last_fa_cnt_ofdm > fa_ofdm) 1094 /* Differential gain gets sent to uCode only once */
1781 data->last_fa_cnt_ofdm = fa_ofdm; 1095 if (!data->radio_write) {
1782 else { 1096 struct iwl4965_calibration_cmd cmd;
1783 fa_ofdm -= data->last_fa_cnt_ofdm; 1097 data->radio_write = 1;
1784 data->last_fa_cnt_ofdm += fa_ofdm;
1785 }
1786 1098
1787 if (data->last_fa_cnt_cck > fa_cck) 1099 memset(&cmd, 0, sizeof(cmd));
1788 data->last_fa_cnt_cck = fa_cck; 1100 cmd.opCode = PHY_CALIBRATE_DIFF_GAIN_CMD;
1789 else { 1101 cmd.diff_gain_a = data->delta_gain_code[0];
1790 fa_cck -= data->last_fa_cnt_cck; 1102 cmd.diff_gain_b = data->delta_gain_code[1];
1791 data->last_fa_cnt_cck += fa_cck; 1103 cmd.diff_gain_c = data->delta_gain_code[2];
1104 ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
1105 sizeof(cmd), &cmd);
1106 if (ret)
1107 IWL_DEBUG_CALIB("fail sending cmd "
1108 "REPLY_PHY_CALIBRATION_CMD \n");
1109
1110 /* TODO we might want recalculate
1111 * rx_chain in rxon cmd */
1112
1113 /* Mark so we run this algo only once! */
1114 data->state = IWL_CHAIN_NOISE_CALIBRATED;
1792 } 1115 }
1793 1116 data->chain_noise_a = 0;
1794 /* Total aborted signal locks */ 1117 data->chain_noise_b = 0;
1795 norm_fa_ofdm = fa_ofdm + bad_plcp_ofdm; 1118 data->chain_noise_c = 0;
1796 norm_fa_cck = fa_cck + bad_plcp_cck; 1119 data->chain_signal_a = 0;
1797 1120 data->chain_signal_b = 0;
1798 IWL_DEBUG_CALIB("cck: fa %u badp %u ofdm: fa %u badp %u\n", fa_cck, 1121 data->chain_signal_c = 0;
1799 bad_plcp_cck, fa_ofdm, bad_plcp_ofdm); 1122 data->beacon_count = 0;
1800
1801 iwl4965_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time);
1802 iwl4965_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis);
1803 ret = iwl4965_sensitivity_write(priv, CMD_ASYNC);
1804
1805 return;
1806} 1123}
1807 1124
1808static void iwl4965_bg_sensitivity_work(struct work_struct *work) 1125static void iwl4965_bg_sensitivity_work(struct work_struct *work)
@@ -1819,21 +1136,15 @@ static void iwl4965_bg_sensitivity_work(struct work_struct *work)
1819 } 1136 }
1820 1137
1821 if (priv->start_calib) { 1138 if (priv->start_calib) {
1822 iwl4965_noise_calibration(priv, &priv->statistics); 1139 iwl_chain_noise_calibration(priv, &priv->statistics);
1823 1140
1824 if (priv->sensitivity_data.state == 1141 iwl_sensitivity_calibration(priv, &priv->statistics);
1825 IWL_SENS_CALIB_NEED_REINIT) {
1826 iwl4965_init_sensitivity(priv, CMD_ASYNC, 0);
1827 priv->sensitivity_data.state = IWL_SENS_CALIB_ALLOWED;
1828 } else
1829 iwl4965_sensitivity_calibration(priv,
1830 &priv->statistics);
1831 } 1142 }
1832 1143
1833 mutex_unlock(&priv->mutex); 1144 mutex_unlock(&priv->mutex);
1834 return; 1145 return;
1835} 1146}
1836#endif /*CONFIG_IWL4965_SENSITIVITY*/ 1147#endif /*CONFIG_IWL4965_RUN_TIME_CALIB*/
1837 1148
1838static void iwl4965_bg_txpower_work(struct work_struct *work) 1149static void iwl4965_bg_txpower_work(struct work_struct *work)
1839{ 1150{
@@ -1932,15 +1243,15 @@ int iwl4965_alive_notify(struct iwl_priv *priv)
1932 1243
1933 spin_lock_irqsave(&priv->lock, flags); 1244 spin_lock_irqsave(&priv->lock, flags);
1934 1245
1935#ifdef CONFIG_IWL4965_SENSITIVITY 1246#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
1936 memset(&(priv->sensitivity_data), 0, 1247 memset(&(priv->sensitivity_data), 0,
1937 sizeof(struct iwl4965_sensitivity_data)); 1248 sizeof(struct iwl_sensitivity_data));
1938 memset(&(priv->chain_noise_data), 0, 1249 memset(&(priv->chain_noise_data), 0,
1939 sizeof(struct iwl4965_chain_noise_data)); 1250 sizeof(struct iwl_chain_noise_data));
1940 for (i = 0; i < NUM_RX_CHAINS; i++) 1251 for (i = 0; i < NUM_RX_CHAINS; i++)
1941 priv->chain_noise_data.delta_gain_code[i] = 1252 priv->chain_noise_data.delta_gain_code[i] =
1942 CHAIN_NOISE_DELTA_GAIN_INIT_VAL; 1253 CHAIN_NOISE_DELTA_GAIN_INIT_VAL;
1943#endif /* CONFIG_IWL4965_SENSITIVITY*/ 1254#endif /* CONFIG_IWL4965_RUN_TIME_CALIB*/
1944 ret = iwl_grab_nic_access(priv); 1255 ret = iwl_grab_nic_access(priv);
1945 if (ret) { 1256 if (ret) {
1946 spin_unlock_irqrestore(&priv->lock, flags); 1257 spin_unlock_irqrestore(&priv->lock, flags);
@@ -2013,6 +1324,31 @@ int iwl4965_alive_notify(struct iwl_priv *priv)
2013 return ret; 1324 return ret;
2014} 1325}
2015 1326
1327#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
1328static struct iwl_sensitivity_ranges iwl4965_sensitivity = {
1329 .min_nrg_cck = 97,
1330 .max_nrg_cck = 0,
1331
1332 .auto_corr_min_ofdm = 85,
1333 .auto_corr_min_ofdm_mrc = 170,
1334 .auto_corr_min_ofdm_x1 = 105,
1335 .auto_corr_min_ofdm_mrc_x1 = 220,
1336
1337 .auto_corr_max_ofdm = 120,
1338 .auto_corr_max_ofdm_mrc = 210,
1339 .auto_corr_max_ofdm_x1 = 140,
1340 .auto_corr_max_ofdm_mrc_x1 = 270,
1341
1342 .auto_corr_min_cck = 125,
1343 .auto_corr_max_cck = 200,
1344 .auto_corr_min_cck_mrc = 200,
1345 .auto_corr_max_cck_mrc = 400,
1346
1347 .nrg_th_cck = 100,
1348 .nrg_th_ofdm = 100,
1349};
1350#endif
1351
2016/** 1352/**
2017 * iwl4965_hw_set_hw_params 1353 * iwl4965_hw_set_hw_params
2018 * 1354 *
@@ -2044,6 +1380,9 @@ int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
2044 priv->hw_params.rx_chains_num = 2; 1380 priv->hw_params.rx_chains_num = 2;
2045 priv->hw_params.valid_tx_ant = (IWL_ANTENNA_MAIN | IWL_ANTENNA_AUX); 1381 priv->hw_params.valid_tx_ant = (IWL_ANTENNA_MAIN | IWL_ANTENNA_AUX);
2046 priv->hw_params.valid_rx_ant = (IWL_ANTENNA_MAIN | IWL_ANTENNA_AUX); 1382 priv->hw_params.valid_rx_ant = (IWL_ANTENNA_MAIN | IWL_ANTENNA_AUX);
1383#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
1384 priv->hw_params.sens = &iwl4965_sensitivity;
1385#endif
2047 1386
2048 return 0; 1387 return 0;
2049} 1388}
@@ -3202,7 +2541,7 @@ void iwl4965_set_rxon_chain(struct iwl_priv *priv)
3202 2541
3203 /* Tell uCode which antennas are actually connected. 2542 /* Tell uCode which antennas are actually connected.
3204 * Before first association, we assume all antennas are connected. 2543 * Before first association, we assume all antennas are connected.
3205 * Just after first association, iwl4965_noise_calibration() 2544 * Just after first association, iwl_chain_noise_calibration()
3206 * checks which antennas actually *are* connected. */ 2545 * checks which antennas actually *are* connected. */
3207 priv->staging_rxon.rx_chain |= 2546 priv->staging_rxon.rx_chain |=
3208 cpu_to_le16(priv->valid_antenna << RXON_RX_CHAIN_VALID_POS); 2547 cpu_to_le16(priv->valid_antenna << RXON_RX_CHAIN_VALID_POS);
@@ -3412,7 +2751,7 @@ void iwl4965_hw_rx_statistics(struct iwl_priv *priv, struct iwl4965_rx_mem_buffe
3412 if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && 2751 if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
3413 (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) { 2752 (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
3414 iwl4965_rx_calc_noise(priv); 2753 iwl4965_rx_calc_noise(priv);
3415#ifdef CONFIG_IWL4965_SENSITIVITY 2754#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
3416 queue_work(priv->workqueue, &priv->sensitivity_work); 2755 queue_work(priv->workqueue, &priv->sensitivity_work);
3417#endif 2756#endif
3418 } 2757 }
@@ -4139,7 +3478,7 @@ static void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv,
4139 struct iwl4965_rx_mem_buffer *rxb) 3478 struct iwl4965_rx_mem_buffer *rxb)
4140 3479
4141{ 3480{
4142#ifdef CONFIG_IWL4965_SENSITIVITY 3481#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
4143 struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; 3482 struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
4144 struct iwl4965_missed_beacon_notif *missed_beacon; 3483 struct iwl4965_missed_beacon_notif *missed_beacon;
4145 3484
@@ -4150,11 +3489,10 @@ static void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv,
4150 le32_to_cpu(missed_beacon->total_missed_becons), 3489 le32_to_cpu(missed_beacon->total_missed_becons),
4151 le32_to_cpu(missed_beacon->num_recvd_beacons), 3490 le32_to_cpu(missed_beacon->num_recvd_beacons),
4152 le32_to_cpu(missed_beacon->num_expected_beacons)); 3491 le32_to_cpu(missed_beacon->num_expected_beacons));
4153 priv->sensitivity_data.state = IWL_SENS_CALIB_NEED_REINIT; 3492 if (!test_bit(STATUS_SCANNING, &priv->status))
4154 if (unlikely(!test_bit(STATUS_SCANNING, &priv->status))) 3493 iwl_init_sensitivity(priv);
4155 queue_work(priv->workqueue, &priv->sensitivity_work);
4156 } 3494 }
4157#endif /*CONFIG_IWL4965_SENSITIVITY*/ 3495#endif /*CONFIG_IWL4965_RUN_TIME_CALIB*/
4158} 3496}
4159#ifdef CONFIG_IWL4965_HT 3497#ifdef CONFIG_IWL4965_HT
4160 3498
@@ -4930,7 +4268,7 @@ void iwl4965_hw_rx_handler_setup(struct iwl_priv *priv)
4930void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv) 4268void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv)
4931{ 4269{
4932 INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work); 4270 INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work);
4933#ifdef CONFIG_IWL4965_SENSITIVITY 4271#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
4934 INIT_WORK(&priv->sensitivity_work, iwl4965_bg_sensitivity_work); 4272 INIT_WORK(&priv->sensitivity_work, iwl4965_bg_sensitivity_work);
4935#endif 4273#endif
4936 init_timer(&priv->statistics_periodic); 4274 init_timer(&priv->statistics_periodic);
@@ -4952,6 +4290,10 @@ static struct iwl_hcmd_ops iwl4965_hcmd = {
4952 4290
4953static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { 4291static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
4954 .enqueue_hcmd = iwl4965_enqueue_hcmd, 4292 .enqueue_hcmd = iwl4965_enqueue_hcmd,
4293#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
4294 .chain_noise_reset = iwl4965_chain_noise_reset,
4295 .gain_computation = iwl4965_gain_computation,
4296#endif
4955}; 4297};
4956 4298
4957static struct iwl_lib_ops iwl4965_lib = { 4299static struct iwl_lib_ops iwl4965_lib = {