Commit 8f91aecb authored by Emmanuel Grumbach's avatar Emmanuel Grumbach Committed by John W. Linville

iwlwifi: move RX stats to core, and move temperature to handler

This patch moves RX stats flow to core modules, and moves temperature
calibration to handler since it is not needed in 5000.
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarZhu Yi <yi.zhu@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 43d59b32
......@@ -555,8 +555,6 @@ static int iwl4965_apm_reset(struct iwl_priv *priv)
return ret;
}
#define REG_RECALIB_PERIOD (60)
/* Reset differential Rx gains in NIC to prepare for chain noise calibration.
* Called after every association, but this runs only once!
* ... once chain noise is calibrated the first time, it's good forever. */
......@@ -1890,80 +1888,15 @@ static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv)
return 1;
}
/* 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 iwl4965_rx_calc_noise(struct iwl_priv *priv)
static void iwl4965_temperature_calib(struct iwl_priv *priv,
struct iwl_notif_statistics *stats)
{
struct statistics_rx_non_phy *rx_info
= &(priv->statistics.rx.general);
int num_active_rx = 0;
int total_silence = 0;
int bcn_silence_a =
le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
int bcn_silence_b =
le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
int 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)
priv->last_rx_noise = (total_silence / num_active_rx) - 107;
else
priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
IWL_DEBUG_CALIB("inband silence a %u, b %u, c %u, dBm %d\n",
bcn_silence_a, bcn_silence_b, bcn_silence_c,
priv->last_rx_noise);
}
void iwl4965_hw_rx_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
int change;
s32 temp;
IWL_DEBUG_RX("Statistics notification received (%d vs %d).\n",
(int)sizeof(priv->statistics), pkt->len);
change = ((priv->statistics.general.temperature !=
pkt->u.stats.general.temperature) ||
int change = ((priv->statistics.general.temperature !=
stats->general.temperature) ||
((priv->statistics.flag &
STATISTICS_REPLY_FLG_FAT_MODE_MSK) !=
(pkt->u.stats.flag & STATISTICS_REPLY_FLG_FAT_MODE_MSK)));
memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
set_bit(STATUS_STATISTICS, &priv->status);
/* Reschedule the statistics timer to occur in
* REG_RECALIB_PERIOD seconds to ensure we get a
* thermal update even if the uCode doesn't give
* us one */
mod_timer(&priv->statistics_periodic, jiffies +
msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
(pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
iwl4965_rx_calc_noise(priv);
queue_work(priv->workqueue, &priv->run_time_calib_work);
}
iwl_leds_background(priv);
(stats->flag & STATISTICS_REPLY_FLG_FAT_MODE_MSK)));
/* If the hardware hasn't reported a change in
* temperature then don't bother computing a
......@@ -3391,6 +3324,7 @@ static struct iwl_lib_ops iwl4965_lib = {
.set_power = iwl4965_set_power,
.send_tx_power = iwl4965_send_tx_power,
.update_chain_flags = iwl4965_update_chain_flags,
.temperature = iwl4965_temperature_calib,
};
static struct iwl_ops iwl4965_ops = {
......
......@@ -1433,6 +1433,12 @@ static int iwl5000_send_tx_power(struct iwl_priv *priv)
NULL);
}
static void iwl5000_temperature(struct iwl_priv *priv,
struct iwl_notif_statistics *stats)
{
/* store temperature from statistics (in Celsius) */
priv->temperature = le32_to_cpu(stats->general.temperature);
}
static struct iwl_hcmd_ops iwl5000_hcmd = {
.rxon_assoc = iwl5000_send_rxon_assoc,
......@@ -1462,6 +1468,7 @@ static struct iwl_lib_ops iwl5000_lib = {
.init_alive_start = iwl5000_init_alive_start,
.alive_notify = iwl5000_alive_notify,
.send_tx_power = iwl5000_send_tx_power,
.temperature = iwl5000_temperature,
.apm_ops = {
.init = iwl5000_apm_init,
.reset = iwl5000_apm_reset,
......
......@@ -470,7 +470,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
EXPORT_SYMBOL(iwl_init_sensitivity);
void iwl_sensitivity_calibration(struct iwl_priv *priv,
struct iwl4965_notif_statistics *resp)
struct iwl_notif_statistics *resp)
{
u32 rx_enable_time;
u32 fa_cck;
......@@ -584,7 +584,7 @@ EXPORT_SYMBOL(iwl_sensitivity_calibration);
* 2) Differential rx gain settings to balance the 3 receivers.
*/
void iwl_chain_noise_calibration(struct iwl_priv *priv,
struct iwl4965_notif_statistics *stat_resp)
struct iwl_notif_statistics *stat_resp)
{
struct iwl_chain_noise_data *data = NULL;
......
......@@ -67,9 +67,9 @@
#include "iwl-commands.h"
void iwl_chain_noise_calibration(struct iwl_priv *priv,
struct iwl4965_notif_statistics *stat_resp);
struct iwl_notif_statistics *stat_resp);
void iwl_sensitivity_calibration(struct iwl_priv *priv,
struct iwl4965_notif_statistics *resp);
struct iwl_notif_statistics *resp);
void iwl_init_sensitivity(struct iwl_priv *priv);
void iwl_reset_run_time_calib(struct iwl_priv *priv);
......
......@@ -2506,7 +2506,7 @@ struct statistics_general {
*/
#define IWL_STATS_CONF_CLEAR_STATS __constant_cpu_to_le32(0x1) /* see above */
#define IWL_STATS_CONF_DISABLE_NOTIF __constant_cpu_to_le32(0x2)/* see above */
struct iwl4965_statistics_cmd {
struct iwl_statistics_cmd {
__le32 configuration_flags; /* IWL_STATS_CONF_* */
} __attribute__ ((packed));
......@@ -2527,7 +2527,7 @@ struct iwl4965_statistics_cmd {
*/
#define STATISTICS_REPLY_FLG_BAND_24G_MSK __constant_cpu_to_le32(0x2)
#define STATISTICS_REPLY_FLG_FAT_MODE_MSK __constant_cpu_to_le32(0x8)
struct iwl4965_notif_statistics {
struct iwl_notif_statistics {
__le32 flag;
struct statistics_rx rx;
struct statistics_tx tx;
......@@ -3000,7 +3000,7 @@ struct iwl_rx_packet {
struct iwl_rem_sta_resp rem_sta;
struct iwl4965_sleep_notification sleep_notif;
struct iwl4965_spectrum_resp spectrum;
struct iwl4965_notif_statistics stats;
struct iwl_notif_statistics stats;
struct iwl4965_compressed_ba_resp compressed_ba;
struct iwl4965_missed_beacon_notif missed_beacon;
struct iwl5000_calibration calib;
......
......@@ -140,6 +140,8 @@ struct iwl_lib_ops {
int (*set_power)(struct iwl_priv *priv, void *cmd);
int (*send_tx_power) (struct iwl_priv *priv);
void (*update_chain_flags)(struct iwl_priv *priv);
void (*temperature) (struct iwl_priv *priv,
struct iwl_notif_statistics *stats);
/* eeprom operations (as defined in iwl-eeprom.h) */
struct iwl_eeprom_ops eeprom_ops;
};
......@@ -218,6 +220,8 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
/* Handlers */
void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
void iwl_rx_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
/* TX helpers */
......
......@@ -624,8 +624,6 @@ extern int iwl_rxq_stop(struct iwl_priv *priv);
extern void iwl_txq_ctx_stop(struct iwl_priv *priv);
extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
struct iwl_frame *frame, u8 rate);
extern void iwl4965_hw_rx_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
extern void iwl4965_disable_events(struct iwl_priv *priv);
extern void iwl4965_rx_reply_rx(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
......@@ -994,7 +992,7 @@ struct iwl_priv {
struct iwl_power_mgr power_data;
struct iwl4965_notif_statistics statistics;
struct iwl_notif_statistics statistics;
unsigned long last_statistics_time;
/* context information */
......
......@@ -466,3 +466,78 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
}
}
EXPORT_SYMBOL(iwl_rx_missed_beacon_notif);
/* 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
= &(priv->statistics.rx.general);
int num_active_rx = 0;
int total_silence = 0;
int bcn_silence_a =
le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
int bcn_silence_b =
le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
int 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)
priv->last_rx_noise = (total_silence / num_active_rx) - 107;
else
priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
IWL_DEBUG_CALIB("inband silence a %u, b %u, c %u, dBm %d\n",
bcn_silence_a, bcn_silence_b, bcn_silence_c,
priv->last_rx_noise);
}
#define REG_RECALIB_PERIOD (60)
void iwl_rx_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
IWL_DEBUG_RX("Statistics notification received (%d vs %d).\n",
(int)sizeof(priv->statistics), pkt->len);
memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
set_bit(STATUS_STATISTICS, &priv->status);
/* Reschedule the statistics timer to occur in
* REG_RECALIB_PERIOD seconds to ensure we get a
* thermal update even if the uCode doesn't give
* us one */
mod_timer(&priv->statistics_periodic, jiffies +
msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
(pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
iwl_rx_calc_noise(priv);
queue_work(priv->workqueue, &priv->run_time_calib_work);
}
iwl_leds_background(priv);
if (priv->cfg->ops->lib->temperature)
priv->cfg->ops->lib->temperature(priv, &pkt->u.stats);
}
EXPORT_SYMBOL(iwl_rx_statistics);
......@@ -1387,8 +1387,8 @@ static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
* statistics request from the host as well as for the periodic
* statistics notifications (after received beacons) from the uCode.
*/
priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl4965_hw_rx_statistics;
priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl4965_hw_rx_statistics;
priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_rx_statistics;
priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics;
iwl_setup_rx_scan_handlers(priv);
......@@ -4130,7 +4130,7 @@ static ssize_t show_statistics(struct device *d,
struct device_attribute *attr, char *buf)
{
struct iwl_priv *priv = dev_get_drvdata(d);
u32 size = sizeof(struct iwl4965_notif_statistics);
u32 size = sizeof(struct iwl_notif_statistics);
u32 len = 0, ofs = 0;
u8 *data = (u8 *) & priv->statistics;
int rc = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment