/* Find max silence rssi among all 3 receivers. *Thisisbackgroundnoise,whichmayincludetransmissionsfromother
* networks, measured during silence before our network's beacon */
silence_rssi_a = (u8)((rx_info->beacon_silence_rssi_a &
ALL_BAND_FILTER) >> 8);
silence_rssi_b = (u8)((rx_info->beacon_silence_rssi_b &
ALL_BAND_FILTER) >> 8);
silence_rssi_c = (u8)((rx_info->beacon_silence_rssi_c &
ALL_BAND_FILTER) >> 8);
val = max(silence_rssi_b, silence_rssi_c);
max_silence_rssi = max(silence_rssi_a, (u8) val);
/* Store silence rssi in 20-beacon history table */
data->nrg_silence_rssi[data->nrg_silence_idx] = max_silence_rssi;
data->nrg_silence_idx++; if (data->nrg_silence_idx >= NRG_NUM_PREV_STAT_L)
data->nrg_silence_idx = 0;
/* Find max silence rssi across 20 beacon history */ for (i = 0; i < NRG_NUM_PREV_STAT_L; i++) {
val = data->nrg_silence_rssi[i];
silence_ref = max(silence_ref, val);
}
IWL_DEBUG_CALIB(priv, "silence a %u, b %u, c %u, 20-bcn max %u\n",
silence_rssi_a, silence_rssi_b, silence_rssi_c,
silence_ref);
/* Find max rx energy (min value!) among all 3 receivers, *measuredduringbeaconframe.
* Save it in 10-beacon history table. */
i = data->nrg_energy_idx;
val = min(rx_info->beacon_energy_b, rx_info->beacon_energy_c);
data->nrg_value[i] = min(rx_info->beacon_energy_a, val);
data->nrg_energy_idx++; if (data->nrg_energy_idx >= 10)
data->nrg_energy_idx = 0;
/* Find min rx energy (max value) across 10 beacon history. *Thisistheminimumsignallevelthatwewanttoreceivewell. *Addbackoff(marginsowedon'tmissslightlylowerenergyframes).
* This establishes an upper bound (min value) for energy threshold. */
max_nrg_cck = data->nrg_value[0]; for (i = 1; i < 10; i++)
max_nrg_cck = (u32) max(max_nrg_cck, (data->nrg_value[i]));
max_nrg_cck += 6;
IWL_DEBUG_CALIB(priv, "rx energy a %u, b %u, c %u, 10-bcn max/min %u\n",
rx_info->beacon_energy_a, rx_info->beacon_energy_b,
rx_info->beacon_energy_c, max_nrg_cck - 6);
/* Count number of consecutive beacons with fewer-than-desired
* false alarms. */ if (false_alarms < min_false_alarms)
data->num_in_cck_no_fa++; else
data->num_in_cck_no_fa = 0;
IWL_DEBUG_CALIB(priv, "consecutive bcns with few false alarms = %u\n",
data->num_in_cck_no_fa);
/* If we got too many false alarms this time, reduce sensitivity */ if ((false_alarms > max_false_alarms) &&
(data->auto_corr_cck > AUTO_CORR_MAX_TH_CCK)) {
IWL_DEBUG_CALIB(priv, "norm FA %u > max FA %u\n",
false_alarms, max_false_alarms);
IWL_DEBUG_CALIB(priv, "... reducing sensitivity\n");
data->nrg_curr_state = IWL_FA_TOO_MANY; /* Store for "fewer than desired" on later beacon */
data->nrg_silence_ref = silence_ref;
/* increase energy threshold (reduce nrg value)
* to decrease sensitivity */
data->nrg_th_cck = data->nrg_th_cck - NRG_STEP_CCK; /* Else if we got fewer than desired, increase sensitivity */
} elseif (false_alarms < min_false_alarms) {
data->nrg_curr_state = IWL_FA_TOO_FEW;
/* Compare silence level with silence level for most recent
* healthy number or too many false alarms */
data->nrg_auto_corr_silence_diff = (s32)data->nrg_silence_ref -
(s32)silence_ref;
IWL_DEBUG_CALIB(priv, "norm FA %u < min FA %u, silence diff %d\n",
false_alarms, min_false_alarms,
data->nrg_auto_corr_silence_diff);
/* Increase value to increase sensitivity, but only if: *1a)previousbeacondid*not*have*toomany*falsealarms *1b)ANDthere'sasignificantdifferenceinRxlevels *fromapreviousbeaconwithtoomany,orhealthy#FAs *OR2)We'veseenalotofbeacons(100)withtoofew
* false alarms */ if ((data->nrg_prev_state != IWL_FA_TOO_MANY) &&
((data->nrg_auto_corr_silence_diff > NRG_DIFF) ||
(data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA))) {
IWL_DEBUG_CALIB(priv, "... increasing sensitivity\n"); /* Increase nrg value to increase sensitivity */
val = data->nrg_th_cck + NRG_STEP_CCK;
data->nrg_th_cck = min((u32)ranges->min_nrg_cck, val);
} else {
IWL_DEBUG_CALIB(priv, "... but not changing sensitivity\n");
}
/* Else we got a healthy number of false alarms, keep status quo */
} else {
IWL_DEBUG_CALIB(priv, " FA in safe zone\n");
data->nrg_curr_state = IWL_FA_GOOD_RANGE;
/* Store for use in "fewer than desired" with later beacon */
data->nrg_silence_ref = silence_ref;
/* If previous beacon had too many false alarms, *giveitsomeextramarginbyreducingsensitivityagain
* (but don't go below measured energy of desired Rx) */ if (data->nrg_prev_state == IWL_FA_TOO_MANY) {
IWL_DEBUG_CALIB(priv, "... increasing margin\n"); if (data->nrg_th_cck > (max_nrg_cck + NRG_MARGIN))
data->nrg_th_cck -= NRG_MARGIN; else
data->nrg_th_cck = max_nrg_cck;
}
}
/* Make sure the energy threshold does not go above the measured *energyofthedesiredRxsignals(reducedbybackoffmargin), *orelsewemightstartmissingRxframes. *Lowervalueishigherenergy,soweusemax()!
*/
data->nrg_th_cck = max(max_nrg_cck, data->nrg_th_cck);
IWL_DEBUG_CALIB(priv, "new nrg_th_cck %u\n", data->nrg_th_cck);
data->nrg_prev_state = data->nrg_curr_state;
/* Auto-correlation CCK algorithm */ if (false_alarms > min_false_alarms) {
/* Update uCode's "work" table, and copy it to DSP */
cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE;
/* Don't send command to uCode if nothing has changed */ if (!memcmp(&cmd.table[0], &(priv->sensitivity_tbl[0]), sizeof(u16)*HD_TABLE_SIZE)) {
IWL_DEBUG_CALIB(priv, "No change in SENSITIVITY_CMD\n"); return0;
}
/* Copy table for comparison next time */
memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]), sizeof(u16)*HD_TABLE_SIZE);
/* Update uCode's "work" table, and copy it to DSP */
cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE;
/* Don't send command to uCode if nothing has changed */ if (!memcmp(&cmd.enhance_table[0], &(priv->sensitivity_tbl[0]), sizeof(u16)*HD_TABLE_SIZE) &&
!memcmp(&cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX],
&(priv->enhance_sensitivity_tbl[0]), sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES)) {
IWL_DEBUG_CALIB(priv, "No change in SENSITIVITY_CMD\n"); return0;
}
/* Copy table for comparison next time */
memcpy(&(priv->sensitivity_tbl[0]), &(cmd.enhance_table[0]), sizeof(u16)*HD_TABLE_SIZE);
memcpy(&(priv->enhance_sensitivity_tbl[0]),
&(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]), sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES);
return iwl_dvm_send_cmd(priv, &cmd_out);
}
void iwl_init_sensitivity(struct iwl_priv *priv)
{ int ret = 0; int i; struct iwl_sensitivity_data *data = NULL; conststruct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
if (priv->calib_disabled & IWL_SENSITIVITY_CALIB_DISABLED) return;
if (priv->fw->enhance_sensitivity_table)
ret |= iwl_enhance_sensitivity_write(priv); else
ret |= iwl_sensitivity_write(priv);
IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret);
}
if (!rx_enable_time) {
IWL_DEBUG_CALIB(priv, "<< RX Enable Time == 0!\n"); return;
}
/* These statistics increase monotonically, and do not reset *ateachbeacon.Calculatedifferencefromlastvalue,orjust
* use the new statistics value if it has reset or wrapped around. */ if (data->last_bad_plcp_cnt_cck > bad_plcp_cck)
data->last_bad_plcp_cnt_cck = bad_plcp_cck; else {
bad_plcp_cck -= data->last_bad_plcp_cnt_cck;
data->last_bad_plcp_cnt_cck += bad_plcp_cck;
}
IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n",
average_sig[0], average_sig[1], average_sig[2]);
IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n",
max_average_sig, max_average_sig_antenna_i);
/* Compare signal strengths for all 3 receivers. */ for (i = 0; i < NUM_RX_CHAINS; i++) { if (i != max_average_sig_antenna_i) {
s32 rssi_delta = (max_average_sig - average_sig[i]);
/* If signal is very weak, compared with
* strongest, mark it as disconnected. */ if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS)
data->disconn_array[i] = 1; else
active_chains |= (1 << i);
IWL_DEBUG_CALIB(priv, "i = %d rssiDelta = %d " "disconn_array[i] = %d\n",
i, rssi_delta, data->disconn_array[i]);
}
}
num_tx_chains = 0; for (i = 0; i < NUM_RX_CHAINS; i++) { /* loops on all the bits of
* priv->hw_setting.valid_tx_ant */
u8 ant_msk = (1 << i); if (!(priv->nvm_data->valid_tx_ant & ant_msk)) continue;
num_tx_chains++; if (data->disconn_array[i] == 0) /* there is a Tx antenna connected */ break; if (num_tx_chains == priv->hw_params.tx_chains_num &&
data->disconn_array[i]) { /* *Ifallchainsaredisconnected *connectthefirstvalidtxchain
*/
first_chain =
find_first_chain(priv->nvm_data->valid_tx_ant);
data->disconn_array[first_chain] = 0;
active_chains |= BIT(first_chain);
IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected W/A - declare %d as connected\n",
first_chain); break;
}
}
if (active_chains != priv->nvm_data->valid_rx_ant &&
active_chains != priv->chain_noise_data.active_chains)
IWL_DEBUG_CALIB(priv, "Detected that not all antennas are connected! " "Connected: %#x, valid: %#x.\n",
active_chains,
priv->nvm_data->valid_rx_ant);
/* Save for use within RXON, TX, SCAN commands, etc. */
data->active_chains = active_chains;
IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n",
active_chains);
}
/* Make sure we accumulate data for just the associated channel
* (even if scanning). */ if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) {
IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n",
rxon_chnum, rxon_band24);
spin_unlock_bh(&priv->statistics.lock); return;
}
IWL_DEBUG_CALIB(priv, "chan=%d, band24=%d, beacon=%d\n",
rxon_chnum, rxon_band24, data->beacon_count);
IWL_DEBUG_CALIB(priv, "chain_sig: a %d b %d c %d\n",
chain_sig_a, chain_sig_b, chain_sig_c);
IWL_DEBUG_CALIB(priv, "chain_noise: a %d b %d c %d\n",
chain_noise_a, chain_noise_b, chain_noise_c);
/* If this is the "chain_noise_num_beacons", determine: *1)Disconnectedantennas(usingsignalstrengths)
* 2) Differential gain (using silence noise) to balance receivers */ if (data->beacon_count != IWL_CAL_NUM_BEACONS) return;
/* Analyze signal for disconnected antenna */ if (priv->lib->bt_params &&
priv->lib->bt_params->advanced_bt_coexist) { /* Disable disconnected antenna algorithm for advanced
bt coex, assuming valid antennas are connected */
data->active_chains = priv->nvm_data->valid_rx_ant; for (i = 0; i < NUM_RX_CHAINS; i++) if (!(data->active_chains & (1<<i)))
data->disconn_array[i] = 1;
} else
iwl_find_disconn_antenna(priv, average_sig, data);
for (i = 0; i < NUM_RX_CHAINS; i++) { if (!(data->disconn_array[i]) &&
(average_noise[i] <= min_average_noise)) { /* This means that chain i is active and has
* lower noise values so far: */
min_average_noise = average_noise[i];
min_average_noise_antenna_i = i;
}
}
IWL_DEBUG_CALIB(priv, "average_noise: a %d b %d c %d\n",
average_noise[0], average_noise[1],
average_noise[2]);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.