Commit ef8d5529 authored by Wey-Yi Guy's avatar Wey-Yi Guy Committed by John W. Linville
Browse files

iwlwifi: update reply_statistics_cmd with 'clear' parameter



When issue REPLY_STATISTICS_CMD to uCode, two possible flag
can be set in the configuration flags

bit 0: Clear statistics
       0: Do not clear Statistics counters
       1: Clear to zero Statistics counters

Allow "clear" parameter to be set from the caller.

Add debugfs file to clear the statistics counters to help monitor and
debug the uCode behavior.
Signed-off-by: default avatarWey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: default avatarReinette Chatre <reinette.chatre@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 7d2ed110
...@@ -612,7 +612,7 @@ static void iwl_bg_statistics_periodic(unsigned long data) ...@@ -612,7 +612,7 @@ static void iwl_bg_statistics_periodic(unsigned long data)
if (!iwl_is_ready_rf(priv)) if (!iwl_is_ready_rf(priv))
return; return;
iwl_send_statistics_request(priv, CMD_ASYNC); iwl_send_statistics_request(priv, CMD_ASYNC, false);
} }
static void iwl_rx_beacon_notif(struct iwl_priv *priv, static void iwl_rx_beacon_notif(struct iwl_priv *priv,
...@@ -729,7 +729,7 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) ...@@ -729,7 +729,7 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv)
* statistics request from the host as well as for the periodic * statistics request from the host as well as for the periodic
* statistics notifications (after received beacons) from the uCode. * statistics notifications (after received beacons) from the uCode.
*/ */
priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_rx_statistics; priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_reply_statistics;
priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics; priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics;
iwl_setup_spectrum_handlers(priv); iwl_setup_spectrum_handlers(priv);
...@@ -2892,7 +2892,7 @@ static ssize_t show_statistics(struct device *d, ...@@ -2892,7 +2892,7 @@ static ssize_t show_statistics(struct device *d,
return -EAGAIN; return -EAGAIN;
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
rc = iwl_send_statistics_request(priv, 0); rc = iwl_send_statistics_request(priv, CMD_SYNC, false);
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
if (rc) { if (rc) {
......
...@@ -900,7 +900,7 @@ void iwl_reset_run_time_calib(struct iwl_priv *priv) ...@@ -900,7 +900,7 @@ void iwl_reset_run_time_calib(struct iwl_priv *priv)
/* Ask for statistics now, the uCode will send notification /* Ask for statistics now, the uCode will send notification
* periodically after association */ * periodically after association */
iwl_send_statistics_request(priv, CMD_ASYNC); iwl_send_statistics_request(priv, CMD_ASYNC, true);
} }
EXPORT_SYMBOL(iwl_reset_run_time_calib); EXPORT_SYMBOL(iwl_reset_run_time_calib);
...@@ -3071,6 +3071,10 @@ struct statistics_general { ...@@ -3071,6 +3071,10 @@ struct statistics_general {
__le32 reserved3; __le32 reserved3;
} __attribute__ ((packed)); } __attribute__ ((packed));
#define UCODE_STATISTICS_CLEAR_MSK (0x1 << 0)
#define UCODE_STATISTICS_FREQUENCY_MSK (0x1 << 1)
#define UCODE_STATISTICS_NARROW_BAND_MSK (0x1 << 2)
/* /*
* REPLY_STATISTICS_CMD = 0x9c, * REPLY_STATISTICS_CMD = 0x9c,
* 3945 and 4965 identical. * 3945 and 4965 identical.
......
...@@ -1990,16 +1990,21 @@ int iwl_send_bt_config(struct iwl_priv *priv) ...@@ -1990,16 +1990,21 @@ int iwl_send_bt_config(struct iwl_priv *priv)
} }
EXPORT_SYMBOL(iwl_send_bt_config); EXPORT_SYMBOL(iwl_send_bt_config);
int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags) int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
{ {
u32 stat_flags = 0; struct iwl_statistics_cmd statistics_cmd = {
struct iwl_host_cmd cmd = { .configuration_flags =
.id = REPLY_STATISTICS_CMD, clear ? IWL_STATS_CONF_CLEAR_STATS : 0,
.flags = flags,
.len = sizeof(stat_flags),
.data = (u8 *) &stat_flags,
}; };
return iwl_send_cmd(priv, &cmd);
if (flags & CMD_ASYNC)
return iwl_send_cmd_pdu_async(priv, REPLY_STATISTICS_CMD,
sizeof(struct iwl_statistics_cmd),
&statistics_cmd, NULL);
else
return iwl_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
sizeof(struct iwl_statistics_cmd),
&statistics_cmd);
} }
EXPORT_SYMBOL(iwl_send_statistics_request); EXPORT_SYMBOL(iwl_send_statistics_request);
......
...@@ -425,6 +425,8 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, ...@@ -425,6 +425,8 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb); struct iwl_rx_mem_buffer *rxb);
void iwl_rx_statistics(struct iwl_priv *priv, void iwl_rx_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb); struct iwl_rx_mem_buffer *rxb);
void iwl_reply_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
/* TX helpers */ /* TX helpers */
...@@ -669,7 +671,8 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv) ...@@ -669,7 +671,8 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv)
extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); extern void iwl_rf_kill_ct_config(struct iwl_priv *priv);
extern int iwl_send_bt_config(struct iwl_priv *priv); extern int iwl_send_bt_config(struct iwl_priv *priv);
extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags); extern int iwl_send_statistics_request(struct iwl_priv *priv,
u8 flags, bool clear);
extern int iwl_verify_ucode(struct iwl_priv *priv); extern int iwl_verify_ucode(struct iwl_priv *priv);
extern int iwl_send_lq_cmd(struct iwl_priv *priv, extern int iwl_send_lq_cmd(struct iwl_priv *priv,
struct iwl_link_quality_cmd *lq, u8 flags); struct iwl_link_quality_cmd *lq, u8 flags);
......
...@@ -107,6 +107,7 @@ struct iwl_debugfs { ...@@ -107,6 +107,7 @@ struct iwl_debugfs {
struct dentry *file_chain_noise; struct dentry *file_chain_noise;
struct dentry *file_tx_power; struct dentry *file_tx_power;
struct dentry *file_power_save_status; struct dentry *file_power_save_status;
struct dentry *file_clear_statistics;
} dbgfs_debug_files; } dbgfs_debug_files;
u32 sram_offset; u32 sram_offset;
u32 sram_len; u32 sram_len;
......
...@@ -1042,10 +1042,6 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, ...@@ -1042,10 +1042,6 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
return simple_read_from_buffer(user_buf, count, ppos, buf, pos); return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
} }
#define UCODE_STATISTICS_CLEAR_MSK (0x1 << 0)
#define UCODE_STATISTICS_FREQUENCY_MSK (0x1 << 1)
#define UCODE_STATISTICS_NARROW_BAND_MSK (0x1 << 2)
static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf,
int bufsz) int bufsz)
{ {
...@@ -1092,7 +1088,7 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, ...@@ -1092,7 +1088,7 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
/* make request to uCode to retrieve statistics information */ /* make request to uCode to retrieve statistics information */
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
ret = iwl_send_statistics_request(priv, 0); ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
if (ret) { if (ret) {
...@@ -1398,7 +1394,7 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, ...@@ -1398,7 +1394,7 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
/* make request to uCode to retrieve statistics information */ /* make request to uCode to retrieve statistics information */
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
ret = iwl_send_statistics_request(priv, 0); ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
if (ret) { if (ret) {
...@@ -1542,7 +1538,7 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, ...@@ -1542,7 +1538,7 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
/* make request to uCode to retrieve statistics information */ /* make request to uCode to retrieve statistics information */
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
ret = iwl_send_statistics_request(priv, 0); ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
if (ret) { if (ret) {
...@@ -1770,7 +1766,7 @@ static ssize_t iwl_dbgfs_tx_power_read(struct file *file, ...@@ -1770,7 +1766,7 @@ static ssize_t iwl_dbgfs_tx_power_read(struct file *file,
else { else {
/* make request to uCode to retrieve statistics information */ /* make request to uCode to retrieve statistics information */
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
ret = iwl_send_statistics_request(priv, 0); ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
if (ret) { if (ret) {
...@@ -1828,6 +1824,30 @@ static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, ...@@ -1828,6 +1824,30 @@ static ssize_t iwl_dbgfs_power_save_status_read(struct file *file,
return simple_read_from_buffer(user_buf, count, ppos, buf, pos); return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
} }
static ssize_t iwl_dbgfs_clear_statistics_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
char buf[8];
int buf_size;
int clear;
memset(buf, 0, sizeof(buf));
buf_size = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
if (sscanf(buf, "%d", &clear) != 1)
return -EFAULT;
/* make request to uCode to retrieve statistics information */
mutex_lock(&priv->mutex);
iwl_send_statistics_request(priv, CMD_SYNC, true);
mutex_unlock(&priv->mutex);
return count;
}
DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics); DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics);
DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics); DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics);
DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
...@@ -1840,6 +1860,7 @@ DEBUGFS_READ_FILE_OPS(sensitivity); ...@@ -1840,6 +1860,7 @@ DEBUGFS_READ_FILE_OPS(sensitivity);
DEBUGFS_READ_FILE_OPS(chain_noise); DEBUGFS_READ_FILE_OPS(chain_noise);
DEBUGFS_READ_FILE_OPS(tx_power); DEBUGFS_READ_FILE_OPS(tx_power);
DEBUGFS_READ_FILE_OPS(power_save_status); DEBUGFS_READ_FILE_OPS(power_save_status);
DEBUGFS_WRITE_FILE_OPS(clear_statistics);
/* /*
* Create the debugfs files and directories * Create the debugfs files and directories
...@@ -1888,6 +1909,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) ...@@ -1888,6 +1909,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(tx_queue, debug); DEBUGFS_ADD_FILE(tx_queue, debug);
DEBUGFS_ADD_FILE(tx_power, debug); DEBUGFS_ADD_FILE(tx_power, debug);
DEBUGFS_ADD_FILE(power_save_status, debug); DEBUGFS_ADD_FILE(power_save_status, debug);
DEBUGFS_ADD_FILE(clear_statistics, debug);
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
DEBUGFS_ADD_FILE(ucode_rx_stats, debug); DEBUGFS_ADD_FILE(ucode_rx_stats, debug);
DEBUGFS_ADD_FILE(ucode_tx_stats, debug); DEBUGFS_ADD_FILE(ucode_tx_stats, debug);
...@@ -1941,6 +1963,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) ...@@ -1941,6 +1963,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_power); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_power);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_power_save_status); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_power_save_status);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_clear_statistics);
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
file_ucode_rx_stats); file_ucode_rx_stats);
......
...@@ -506,7 +506,7 @@ static void iwl_prepare_ct_kill_task(struct iwl_priv *priv) ...@@ -506,7 +506,7 @@ static void iwl_prepare_ct_kill_task(struct iwl_priv *priv)
{ {
IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n"); IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n");
/* make request to retrieve statistics information */ /* make request to retrieve statistics information */
iwl_send_statistics_request(priv, 0); iwl_send_statistics_request(priv, CMD_SYNC, false);
/* Reschedule the ct_kill wait timer */ /* Reschedule the ct_kill wait timer */
mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm, mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm,
jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION)); jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION));
......
...@@ -635,6 +635,24 @@ void iwl_rx_statistics(struct iwl_priv *priv, ...@@ -635,6 +635,24 @@ void iwl_rx_statistics(struct iwl_priv *priv,
} }
EXPORT_SYMBOL(iwl_rx_statistics); EXPORT_SYMBOL(iwl_rx_statistics);
void iwl_reply_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
memset(&priv->statistics, 0,
sizeof(struct iwl_notif_statistics));
#ifdef CONFIG_IWLWIFI_DEBUG
memset(&priv->accum_statistics, 0,
sizeof(struct iwl_notif_statistics));
#endif
IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
}
iwl_rx_statistics(priv, rxb);
}
EXPORT_SYMBOL(iwl_reply_statistics);
#define PERFECT_RSSI (-20) /* dBm */ #define PERFECT_RSSI (-20) /* dBm */
#define WORST_RSSI (-95) /* dBm */ #define WORST_RSSI (-95) /* dBm */
#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI) #define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)
......
...@@ -3649,7 +3649,7 @@ static ssize_t show_statistics(struct device *d, ...@@ -3649,7 +3649,7 @@ static ssize_t show_statistics(struct device *d,
return -EAGAIN; return -EAGAIN;
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
rc = iwl_send_statistics_request(priv, 0); rc = iwl_send_statistics_request(priv, CMD_SYNC, false);
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
if (rc) { if (rc) {
......
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