static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) { struct iwl_calib_temperature_offset_v2_cmd cmd; __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_KELVIN_TEMPERATURE); __le16 *offset_calib_low = (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); struct iwl_eeprom_calib_hdr *hdr; memset(&cmd, 0, sizeof(cmd)); iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, EEPROM_CALIB_ALL); memcpy(&cmd.radio_sensor_offset_high, offset_calib_high, sizeof(*offset_calib_high)); memcpy(&cmd.radio_sensor_offset_low, offset_calib_low, sizeof(*offset_calib_low)); if (!(cmd.radio_sensor_offset_low)) { IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n"); cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET; cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET; } memcpy(&cmd.burntVoltageRef, &hdr->voltage, sizeof(hdr->voltage)); IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n", le16_to_cpu(cmd.radio_sensor_offset_high)); IWL_DEBUG_CALIB(priv, "Radio sensor offset low: %d\n", le16_to_cpu(cmd.radio_sensor_offset_low)); IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n", le16_to_cpu(cmd.burntVoltageRef)); return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); }
static void iwlagn_chain_noise_reset(struct iwl_priv *priv) { struct iwl_chain_noise_data *data = &priv->chain_noise_data; int ret; if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_any_associated(priv)) { struct iwl_calib_chain_noise_reset_cmd cmd; /* clear data for chain noise calibration algorithm */ data->chain_noise_a = 0; data->chain_noise_b = 0; data->chain_noise_c = 0; data->chain_signal_a = 0; data->chain_signal_b = 0; data->chain_signal_c = 0; data->beacon_count = 0; memset(&cmd, 0, sizeof(cmd)); cmd.hdr.op_code = priv->_agn.phy_calib_chain_noise_reset_cmd; cmd.hdr.first_group = 0; cmd.hdr.groups_num = 1; cmd.hdr.data_valid = 1; ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, sizeof(cmd), &cmd); if (ret) IWL_ERR(priv, "Could not send REPLY_PHY_CALIBRATION_CMD\n"); data->state = IWL_CHAIN_NOISE_ACCUMULATE; IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n"); } }
static void iwlagn_gain_computation(struct iwl_priv *priv, u32 average_noise[NUM_RX_CHAINS], u16 min_average_noise_antenna_i, u32 min_average_noise, u8 default_chain) { int i; s32 delta_g; struct iwl_chain_noise_data *data = &priv->chain_noise_data; /* * Find Gain Code for the chains based on "default chain" */ for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) { if ((data->disconn_array[i])) { data->delta_gain_code[i] = 0; continue; } delta_g = (priv->cfg->base_params->chain_noise_scale * ((s32)average_noise[default_chain] - (s32)average_noise[i])) / 1500; /* bound gain by 2 bits value max, 3rd bit is sign */ data->delta_gain_code[i] = min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); if (delta_g < 0) /* * set negative sign ... * note to Intel developers: This is uCode API format, * not the format of any internal device registers. * Do not change this format for e.g. 6050 or similar * devices. Change format only if more resolution * (i.e. more than 2 bits magnitude) is needed. */ data->delta_gain_code[i] |= (1 << 2); } IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d ANT_C = %d\n", data->delta_gain_code[1], data->delta_gain_code[2]); if (!data->radio_write) { struct iwl_calib_chain_noise_gain_cmd cmd; memset(&cmd, 0, sizeof(cmd)); cmd.hdr.op_code = priv->_agn.phy_calib_chain_noise_gain_cmd; cmd.hdr.first_group = 0; cmd.hdr.groups_num = 1; cmd.hdr.data_valid = 1; cmd.delta_gain_1 = data->delta_gain_code[1]; cmd.delta_gain_2 = data->delta_gain_code[2]; iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD, sizeof(cmd), &cmd, NULL); data->radio_write = 1; data->state = IWL_CHAIN_NOISE_CALIBRATED; } }
static void iwl5000_gain_computation(struct iwl_priv *priv, u32 average_noise[NUM_RX_CHAINS], u16 min_average_noise_antenna_i, u32 min_average_noise) { int i; s32 delta_g; struct iwl_chain_noise_data *data = &priv->chain_noise_data; /* Find Gain Code for the antennas B and C */ for (i = 1; i < NUM_RX_CHAINS; i++) { if ((data->disconn_array[i])) { data->delta_gain_code[i] = 0; continue; } delta_g = (1000 * ((s32)average_noise[0] - (s32)average_noise[i])) / 1500; /* bound gain by 2 bits value max, 3rd bit is sign */ data->delta_gain_code[i] = min(abs(delta_g), CHAIN_NOISE_MAX_DELTA_GAIN_CODE); if (delta_g < 0) /* set negative sign */ data->delta_gain_code[i] |= (1 << 2); } IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d ANT_C = %d\n", data->delta_gain_code[1], data->delta_gain_code[2]); if (!data->radio_write) { struct iwl_calib_chain_noise_gain_cmd cmd; memset(&cmd, 0, sizeof(cmd)); cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD; cmd.hdr.first_group = 0; cmd.hdr.groups_num = 1; cmd.hdr.data_valid = 1; cmd.delta_gain_1 = data->delta_gain_code[1]; cmd.delta_gain_2 = data->delta_gain_code[2]; iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD, sizeof(cmd), &cmd, NULL); data->radio_write = 1; data->state = IWL_CHAIN_NOISE_CALIBRATED; } data->chain_noise_a = 0; data->chain_noise_b = 0; data->chain_noise_c = 0; data->chain_signal_a = 0; data->chain_signal_b = 0; data->chain_signal_c = 0; data->beacon_count = 0; }
static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) { struct iwl_calib_temperature_offset_cmd cmd; memset(&cmd, 0, sizeof(cmd)); iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); cmd.radio_sensor_offset = priv->nvm_data->raw_temperature; if (!(cmd.radio_sensor_offset)) cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n", le16_to_cpu(cmd.radio_sensor_offset)); return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); }
static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) { struct iwl_calib_temperature_offset_v2_cmd cmd; memset(&cmd, 0, sizeof(cmd)); iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); cmd.radio_sensor_offset_high = priv->nvm_data->kelvin_temperature; cmd.radio_sensor_offset_low = priv->nvm_data->raw_temperature; if (!cmd.radio_sensor_offset_low) { IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n"); cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET; cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET; } cmd.burntVoltageRef = priv->nvm_data->calib_voltage; IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n", le16_to_cpu(cmd.radio_sensor_offset_high)); IWL_DEBUG_CALIB(priv, "Radio sensor offset low: %d\n", le16_to_cpu(cmd.radio_sensor_offset_low)); IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n", le16_to_cpu(cmd.burntVoltageRef)); return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); }
static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) { struct iwl_calib_temperature_offset_cmd cmd; __le16 *offset_calib = (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); memset(&cmd, 0, sizeof(cmd)); iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); memcpy(&cmd.radio_sensor_offset, offset_calib, sizeof(*offset_calib)); if (!(cmd.radio_sensor_offset)) cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n", le16_to_cpu(cmd.radio_sensor_offset)); return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); }
static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv) { struct iwl_calib_temperature_offset_cmd cmd; __le16 *offset_calib = (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE); cmd.hdr.op_code = IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD; cmd.hdr.first_group = 0; cmd.hdr.groups_num = 1; cmd.hdr.data_valid = 1; cmd.radio_sensor_offset = le16_to_cpu(offset_calib[1]); if (!(cmd.radio_sensor_offset)) cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; cmd.reserved = 0; IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n", cmd.radio_sensor_offset); return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET], (u8 *)&cmd, sizeof(cmd)); }
void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; struct iwl_missed_beacon_notif *missed_beacon; missed_beacon = &pkt->u.missed_beacon; if (le32_to_cpu(missed_beacon->consequtive_missed_beacons) > 5) { IWL_DEBUG_CALIB(priv, "missed bcn cnsq %d totl %d rcd %d expctd %d\n", le32_to_cpu(missed_beacon->consequtive_missed_beacons), le32_to_cpu(missed_beacon->total_missed_becons), le32_to_cpu(missed_beacon->num_recvd_beacons), le32_to_cpu(missed_beacon->num_expected_beacons)); if (!test_bit(STATUS_SCANNING, &priv->status)) iwl_init_sensitivity(priv); } }
/* Calculate noise level, based on measurements during network silence just * before arriving beacon. This measurement can be done only if we know * exactly when to expect beacons, therefore only when we're associated. */ static void iwl_rx_calc_noise(struct iwl_priv *priv) { struct statistics_rx_non_phy *rx_info; int num_active_rx = 0; int total_silence = 0; int bcn_silence_a, bcn_silence_b, bcn_silence_c; int last_rx_noise; if (iwl_bt_statistics(priv)) rx_info = &(priv->_agn.statistics_bt.rx.general.common); else rx_info = &(priv->_agn.statistics.rx.general); bcn_silence_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER; bcn_silence_b = le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER; bcn_silence_c = le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER; if (bcn_silence_a) { total_silence += bcn_silence_a; num_active_rx++; } if (bcn_silence_b) { total_silence += bcn_silence_b; num_active_rx++; } if (bcn_silence_c) { total_silence += bcn_silence_c; num_active_rx++; } /* Average among active antennas */ if (num_active_rx) last_rx_noise = (total_silence / num_active_rx) - 107; else last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n", bcn_silence_a, bcn_silence_b, bcn_silence_c, last_rx_noise); }
static void iwl5000_chain_noise_reset(struct iwl_priv *priv) { struct iwl_chain_noise_data *data = &priv->chain_noise_data; int ret; if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { struct iwl_calib_chain_noise_reset_cmd cmd; memset(&cmd, 0, sizeof(cmd)); cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; cmd.hdr.first_group = 0; cmd.hdr.groups_num = 1; cmd.hdr.data_valid = 1; ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, sizeof(cmd), &cmd); if (ret) IWL_ERR(priv, "Could not send REPLY_PHY_CALIBRATION_CMD\n"); data->state = IWL_CHAIN_NOISE_ACCUMULATE; IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n"); } }
static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) { struct iwl_phy_cfg_cmd phy_cfg_cmd; enum iwl_ucode_type ucode_type = mvm->fwrt.cur_fw_img; #ifdef CPTCFG_IWLWIFI_SUPPORT_DEBUG_OVERRIDES u32 override_mask, flow_override, flow_src; u32 event_override, event_src; const struct iwl_tlv_calib_ctrl *default_calib = &mvm->fw->default_calib[ucode_type]; #endif /* Set parameters */ phy_cfg_cmd.phy_cfg = cpu_to_le32(iwl_mvm_get_phy_config(mvm)); /* set flags extra PHY configuration flags from the device's cfg */ phy_cfg_cmd.phy_cfg |= cpu_to_le32(mvm->cfg->extra_phy_cfg_flags); phy_cfg_cmd.calib_control.event_trigger = mvm->fw->default_calib[ucode_type].event_trigger; phy_cfg_cmd.calib_control.flow_trigger = mvm->fw->default_calib[ucode_type].flow_trigger; #ifdef CPTCFG_IWLWIFI_SUPPORT_DEBUG_OVERRIDES override_mask = mvm->trans->dbg_cfg.MVM_CALIB_OVERRIDE_CONTROL; if (override_mask) { IWL_DEBUG_INFO(mvm, "calib settings overriden by user, control=0x%x\n", override_mask); switch (ucode_type) { case IWL_UCODE_INIT: flow_override = mvm->trans->dbg_cfg.MVM_CALIB_INIT_FLOW; event_override = mvm->trans->dbg_cfg.MVM_CALIB_INIT_EVENT; IWL_DEBUG_CALIB(mvm, "INIT: flow_override %x, event_override %x\n", flow_override, event_override); break; case IWL_UCODE_REGULAR: flow_override = mvm->trans->dbg_cfg.MVM_CALIB_D0_FLOW; event_override = mvm->trans->dbg_cfg.MVM_CALIB_D0_EVENT; IWL_DEBUG_CALIB(mvm, "REGULAR: flow_override %x, event_override %x\n", flow_override, event_override); break; case IWL_UCODE_WOWLAN: flow_override = mvm->trans->dbg_cfg.MVM_CALIB_D3_FLOW; event_override = mvm->trans->dbg_cfg.MVM_CALIB_D3_EVENT; IWL_DEBUG_CALIB(mvm, "WOWLAN: flow_override %x, event_override %x\n", flow_override, event_override); break; default: IWL_ERR(mvm, "ERROR: calib case isn't valid\n"); flow_override = 0; event_override = 0; break; } IWL_DEBUG_CALIB(mvm, "override_mask %x\n", override_mask); /* find the new calib setting for the flow calibrations */ flow_src = le32_to_cpu(default_calib->flow_trigger); IWL_DEBUG_CALIB(mvm, "flow_src %x\n", flow_src); flow_override &= override_mask; flow_src &= ~override_mask; flow_override |= flow_src; phy_cfg_cmd.calib_control.flow_trigger = cpu_to_le32(flow_override); IWL_DEBUG_CALIB(mvm, "new flow calib setting = %x\n", flow_override); /* find the new calib setting for the event calibrations */ event_src = le32_to_cpu(default_calib->event_trigger); IWL_DEBUG_CALIB(mvm, "event_src %x\n", event_src); event_override &= override_mask; event_src &= ~override_mask; event_override |= event_src; phy_cfg_cmd.calib_control.event_trigger = cpu_to_le32(event_override); IWL_DEBUG_CALIB(mvm, "new event calib setting = %x\n", event_override); } #endif IWL_DEBUG_INFO(mvm, "Sending Phy CFG command: 0x%x\n", phy_cfg_cmd.phy_cfg); return iwl_mvm_send_cmd_pdu(mvm, PHY_CONFIGURATION_CMD, 0, sizeof(phy_cfg_cmd), &phy_cfg_cmd); }