395 lines
16 KiB
Diff
395 lines
16 KiB
Diff
Backport of the following upstream commit...
|
|
|
|
commit 3e4fb5faefb57824f2e42305b3d5907845af978c
|
|
Author: Trieu 'Andrew' Nguyen <trieux.t.nguyen@intel.com>
|
|
Date: Fri Jan 22 14:22:46 2010 -0800
|
|
|
|
iwlwifi: Tune radio to prevent unexpected behavior
|
|
|
|
We have seen the throughput dropped due to external noisy environment
|
|
and the radio is out of tune. There are lot of plcp errors indicating
|
|
this condition. Eventually the station can get de-authenticated by the
|
|
Access Point. By resetting and tuning the radio, the plcp errors are
|
|
reduced or eliminated and the throughput starts to rise.
|
|
|
|
To prevent unexpected behavior such as drop in throughput or deauthentication,
|
|
- The change provides the driver feature to monitor and tune the radio base on
|
|
the statistics notification from the uCode.
|
|
- It also allows the setting of the plcp error rate threshold via
|
|
the plcp_delta under debugfs interface.
|
|
|
|
Signed-off-by: Trieu 'Andrew' Nguyen <trieux.t.nguyen@intel.com>
|
|
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
diff -up linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-1000.c.orig linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-1000.c
|
|
--- linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-1000.c.orig 2010-04-13 14:30:36.000000000 -0400
|
|
+++ linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-1000.c 2010-04-13 14:30:41.000000000 -0400
|
|
@@ -174,6 +174,7 @@ struct iwl_cfg iwl1000_bgn_cfg = {
|
|
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
|
.support_ct_kill_exit = true,
|
|
.sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
|
|
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
|
};
|
|
|
|
struct iwl_cfg iwl1000_bg_cfg = {
|
|
@@ -200,6 +201,7 @@ struct iwl_cfg iwl1000_bg_cfg = {
|
|
.led_compensation = 51,
|
|
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
|
.support_ct_kill_exit = true,
|
|
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
|
};
|
|
|
|
MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX));
|
|
diff -up linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-3945.c.orig linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-3945.c
|
|
--- linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-3945.c.orig 2010-04-13 14:30:36.000000000 -0400
|
|
+++ linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-3945.c 2010-04-13 14:30:41.000000000 -0400
|
|
@@ -2828,6 +2828,7 @@ static struct iwl_cfg iwl3945_bg_cfg = {
|
|
.ht_greenfield_support = false,
|
|
.led_compensation = 64,
|
|
.broken_powersave = true,
|
|
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
|
};
|
|
|
|
static struct iwl_cfg iwl3945_abg_cfg = {
|
|
@@ -2845,6 +2846,7 @@ static struct iwl_cfg iwl3945_abg_cfg =
|
|
.ht_greenfield_support = false,
|
|
.led_compensation = 64,
|
|
.broken_powersave = true,
|
|
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
|
};
|
|
|
|
struct pci_device_id iwl3945_hw_card_ids[] = {
|
|
diff -up linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-4965.c.orig linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-4965.c
|
|
--- linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-4965.c.orig 2010-04-13 14:30:36.000000000 -0400
|
|
+++ linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-4965.c 2010-04-13 14:30:41.000000000 -0400
|
|
@@ -2247,6 +2247,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
|
|
.led_compensation = 61,
|
|
.chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
|
|
.sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
|
|
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
|
};
|
|
|
|
/* Module firmware */
|
|
diff -up linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-5000.c.orig linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-5000.c
|
|
--- linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-5000.c.orig 2010-04-13 14:30:36.000000000 -0400
|
|
+++ linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-5000.c 2010-04-13 14:30:41.000000000 -0400
|
|
@@ -1606,6 +1606,7 @@ struct iwl_cfg iwl5300_agn_cfg = {
|
|
.use_rts_for_ht = true, /* use rts/cts protection */
|
|
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
|
.sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
|
|
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
|
};
|
|
|
|
struct iwl_cfg iwl5100_bgn_cfg = {
|
|
@@ -1630,6 +1631,7 @@ struct iwl_cfg iwl5100_bgn_cfg = {
|
|
.led_compensation = 51,
|
|
.use_rts_for_ht = true, /* use rts/cts protection */
|
|
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
|
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
|
};
|
|
|
|
struct iwl_cfg iwl5100_abg_cfg = {
|
|
@@ -1652,6 +1654,7 @@ struct iwl_cfg iwl5100_abg_cfg = {
|
|
.use_bsm = false,
|
|
.led_compensation = 51,
|
|
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
|
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
|
};
|
|
|
|
struct iwl_cfg iwl5100_agn_cfg = {
|
|
@@ -1677,6 +1680,7 @@ struct iwl_cfg iwl5100_agn_cfg = {
|
|
.use_rts_for_ht = true, /* use rts/cts protection */
|
|
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
|
.sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
|
|
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
|
};
|
|
|
|
struct iwl_cfg iwl5350_agn_cfg = {
|
|
@@ -1702,6 +1706,7 @@ struct iwl_cfg iwl5350_agn_cfg = {
|
|
.use_rts_for_ht = true, /* use rts/cts protection */
|
|
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
|
.sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
|
|
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
|
};
|
|
|
|
struct iwl_cfg iwl5150_agn_cfg = {
|
|
@@ -1727,6 +1732,7 @@ struct iwl_cfg iwl5150_agn_cfg = {
|
|
.use_rts_for_ht = true, /* use rts/cts protection */
|
|
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
|
.sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
|
|
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
|
};
|
|
|
|
struct iwl_cfg iwl5150_abg_cfg = {
|
|
@@ -1749,6 +1755,7 @@ struct iwl_cfg iwl5150_abg_cfg = {
|
|
.use_bsm = false,
|
|
.led_compensation = 51,
|
|
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
|
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
|
};
|
|
|
|
MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
|
|
diff -up linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-6000.c.orig linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-6000.c
|
|
--- linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-6000.c.orig 2010-04-13 14:30:36.000000000 -0400
|
|
+++ linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-6000.c 2010-04-13 14:32:09.000000000 -0400
|
|
@@ -307,6 +307,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
|
|
.adv_thermal_throttle = true,
|
|
.support_ct_kill_exit = true,
|
|
.sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
|
|
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
|
};
|
|
|
|
struct iwl_cfg iwl6000i_2abg_cfg = {
|
|
@@ -336,6 +337,7 @@ struct iwl_cfg iwl6000i_2abg_cfg = {
|
|
.supports_idle = true,
|
|
.adv_thermal_throttle = true,
|
|
.support_ct_kill_exit = true,
|
|
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
|
};
|
|
|
|
struct iwl_cfg iwl6000i_2bg_cfg = {
|
|
@@ -365,6 +367,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
|
|
.supports_idle = true,
|
|
.adv_thermal_throttle = true,
|
|
.support_ct_kill_exit = true,
|
|
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
|
};
|
|
|
|
struct iwl_cfg iwl6050_2agn_cfg = {
|
|
@@ -396,6 +399,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
|
|
.adv_thermal_throttle = true,
|
|
.support_ct_kill_exit = true,
|
|
.sm_ps_mode = WLAN_HT_CAP_SM_PS_DYNAMIC,
|
|
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
|
};
|
|
|
|
struct iwl_cfg iwl6050_2abg_cfg = {
|
|
@@ -425,6 +429,7 @@ struct iwl_cfg iwl6050_2abg_cfg = {
|
|
.supports_idle = true,
|
|
.adv_thermal_throttle = true,
|
|
.support_ct_kill_exit = true,
|
|
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
|
};
|
|
|
|
struct iwl_cfg iwl6000_3agn_cfg = {
|
|
@@ -456,6 +461,7 @@ struct iwl_cfg iwl6000_3agn_cfg = {
|
|
.adv_thermal_throttle = true,
|
|
.support_ct_kill_exit = true,
|
|
.sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
|
|
+ .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
|
};
|
|
|
|
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
|
|
diff -up linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-core.h.orig linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-core.h
|
|
--- linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-core.h.orig 2010-04-13 14:30:36.000000000 -0400
|
|
+++ linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-core.h 2010-04-13 14:30:41.000000000 -0400
|
|
@@ -232,6 +232,8 @@ struct iwl_mod_params {
|
|
* @support_ct_kill_exit: support ct kill exit condition
|
|
* @sm_ps_mode: spatial multiplexing power save mode
|
|
* @support_wimax_coexist: support wimax/wifi co-exist
|
|
+ * @plcp_delta_threshold: plcp error rate threshold used to trigger
|
|
+ * radio tuning when there is a high receiving plcp error rate
|
|
*
|
|
* We enable the driver to be backward compatible wrt API version. The
|
|
* driver specifies which APIs it supports (with @ucode_api_max being the
|
|
@@ -289,6 +291,7 @@ struct iwl_cfg {
|
|
bool support_ct_kill_exit;
|
|
u8 sm_ps_mode;
|
|
const bool support_wimax_coexist;
|
|
+ u8 plcp_delta_threshold;
|
|
};
|
|
|
|
/***************************
|
|
diff -up linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-debugfs.c.orig linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-debugfs.c
|
|
--- linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-debugfs.c.orig 2010-04-13 14:30:36.000000000 -0400
|
|
+++ linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-debugfs.c 2010-04-13 14:30:41.000000000 -0400
|
|
@@ -1866,6 +1866,47 @@ static ssize_t iwl_dbgfs_internal_scan_w
|
|
return count;
|
|
}
|
|
|
|
+static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file,
|
|
+ char __user *user_buf,
|
|
+ size_t count, loff_t *ppos) {
|
|
+
|
|
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
|
|
+ int pos = 0;
|
|
+ char buf[12];
|
|
+ const size_t bufsz = sizeof(buf);
|
|
+ ssize_t ret;
|
|
+
|
|
+ pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
|
|
+ priv->cfg->plcp_delta_threshold);
|
|
+
|
|
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static ssize_t iwl_dbgfs_plcp_delta_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 plcp;
|
|
+
|
|
+ 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", &plcp) != 1)
|
|
+ return -EINVAL;
|
|
+ if ((plcp <= IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
|
|
+ (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
|
|
+ priv->cfg->plcp_delta_threshold =
|
|
+ IWL_MAX_PLCP_ERR_THRESHOLD_DEF;
|
|
+ else
|
|
+ priv->cfg->plcp_delta_threshold = plcp;
|
|
+ return count;
|
|
+}
|
|
+
|
|
DEBUGFS_READ_FILE_OPS(rx_statistics);
|
|
DEBUGFS_READ_FILE_OPS(tx_statistics);
|
|
DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
|
|
@@ -1881,6 +1922,7 @@ DEBUGFS_READ_FILE_OPS(power_save_status)
|
|
DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
|
|
DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
|
|
DEBUGFS_WRITE_FILE_OPS(internal_scan);
|
|
+DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
|
|
|
|
/*
|
|
* Create the debugfs files and directories
|
|
@@ -1932,6 +1974,7 @@ int iwl_dbgfs_register(struct iwl_priv *
|
|
DEBUGFS_ADD_FILE(clear_ucode_statistics, debug, S_IWUSR);
|
|
DEBUGFS_ADD_FILE(clear_traffic_statistics, debug, S_IWUSR);
|
|
DEBUGFS_ADD_FILE(internal_scan, debug, S_IWUSR);
|
|
+ DEBUGFS_ADD_FILE(plcp_delta, debug, S_IWUSR | S_IRUSR);
|
|
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
|
|
DEBUGFS_ADD_FILE(ucode_rx_stats, debug, S_IRUSR);
|
|
DEBUGFS_ADD_FILE(ucode_tx_stats, debug, S_IRUSR);
|
|
@@ -1990,6 +2033,7 @@ void iwl_dbgfs_unregister(struct iwl_pri
|
|
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
|
|
file_clear_traffic_statistics);
|
|
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_internal_scan);
|
|
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_plcp_delta);
|
|
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
|
|
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
|
|
file_ucode_rx_stats);
|
|
diff -up linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-debug.h.orig linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-debug.h
|
|
--- linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-debug.h.orig 2010-04-13 14:30:36.000000000 -0400
|
|
+++ linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-debug.h 2010-04-13 14:30:41.000000000 -0400
|
|
@@ -110,6 +110,7 @@ struct iwl_debugfs {
|
|
struct dentry *file_clear_ucode_statistics;
|
|
struct dentry *file_clear_traffic_statistics;
|
|
struct dentry *file_internal_scan;
|
|
+ struct dentry *file_plcp_delta;
|
|
} dbgfs_debug_files;
|
|
u32 sram_offset;
|
|
u32 sram_len;
|
|
diff -up linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h.orig linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h
|
|
--- linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h.orig 2010-04-13 14:30:36.000000000 -0400
|
|
+++ linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h 2010-04-13 14:30:41.000000000 -0400
|
|
@@ -984,6 +984,15 @@ struct iwl_switch_rxon {
|
|
__le16 channel;
|
|
};
|
|
|
|
+/*
|
|
+ * This is the threshold value of plcp error rate per 100mSecs. It is
|
|
+ * used to set and check for the validity of plcp_delta.
|
|
+ */
|
|
+#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (0)
|
|
+#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50)
|
|
+#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100)
|
|
+#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255)
|
|
+
|
|
struct iwl_priv {
|
|
|
|
/* ieee device used by generic ieee processing code */
|
|
@@ -1012,6 +1021,9 @@ struct iwl_priv {
|
|
/* ucode beacon time */
|
|
u32 ucode_beacon_time;
|
|
|
|
+ /* storing the jiffies when the plcp error rate is received */
|
|
+ unsigned long plcp_jiffies;
|
|
+
|
|
/* we allocate array of iwl4965_channel_info for NIC's valid channels.
|
|
* Access via channel # using indirect index array */
|
|
struct iwl_channel_info *channel_info; /* channel info array */
|
|
diff -up linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-rx.c.orig linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-rx.c
|
|
--- linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-rx.c.orig 2010-04-13 14:30:36.000000000 -0400
|
|
+++ linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-rx.c 2010-04-13 14:30:41.000000000 -0400
|
|
@@ -593,11 +593,15 @@ static void iwl_accumulative_statistics(
|
|
|
|
#define REG_RECALIB_PERIOD (60)
|
|
|
|
+#define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n"
|
|
void iwl_rx_statistics(struct iwl_priv *priv,
|
|
struct iwl_rx_mem_buffer *rxb)
|
|
{
|
|
int change;
|
|
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
|
+ int combined_plcp_delta;
|
|
+ unsigned int plcp_msec;
|
|
+ unsigned long plcp_received_jiffies;
|
|
|
|
IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
|
|
(int)sizeof(priv->statistics),
|
|
@@ -612,6 +616,56 @@ void iwl_rx_statistics(struct iwl_priv *
|
|
#ifdef CONFIG_IWLWIFI_DEBUG
|
|
iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
|
|
#endif
|
|
+ /*
|
|
+ * check for plcp_err and trigger radio reset if it exceeds
|
|
+ * the plcp error threshold plcp_delta.
|
|
+ */
|
|
+ plcp_received_jiffies = jiffies;
|
|
+ plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
|
|
+ (long) priv->plcp_jiffies);
|
|
+ priv->plcp_jiffies = plcp_received_jiffies;
|
|
+ /*
|
|
+ * check to make sure plcp_msec is not 0 to prevent division
|
|
+ * by zero.
|
|
+ */
|
|
+ if (plcp_msec) {
|
|
+ combined_plcp_delta =
|
|
+ (le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) -
|
|
+ le32_to_cpu(priv->statistics.rx.ofdm.plcp_err)) +
|
|
+ (le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) -
|
|
+ le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err));
|
|
+
|
|
+ if ((combined_plcp_delta > 0) &&
|
|
+ ((combined_plcp_delta * 100) / plcp_msec) >
|
|
+ priv->cfg->plcp_delta_threshold) {
|
|
+ /*
|
|
+ * if plcp_err exceed the threshold, the following
|
|
+ * data is printed in csv format:
|
|
+ * Text: plcp_err exceeded %d,
|
|
+ * Received ofdm.plcp_err,
|
|
+ * Current ofdm.plcp_err,
|
|
+ * Received ofdm_ht.plcp_err,
|
|
+ * Current ofdm_ht.plcp_err,
|
|
+ * combined_plcp_delta,
|
|
+ * plcp_msec
|
|
+ */
|
|
+ IWL_DEBUG_RADIO(priv, PLCP_MSG,
|
|
+ priv->cfg->plcp_delta_threshold,
|
|
+ le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err),
|
|
+ le32_to_cpu(priv->statistics.rx.ofdm.plcp_err),
|
|
+ le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err),
|
|
+ le32_to_cpu(
|
|
+ priv->statistics.rx.ofdm_ht.plcp_err),
|
|
+ combined_plcp_delta, plcp_msec);
|
|
+
|
|
+ /*
|
|
+ * Reset the RF radio due to the high plcp
|
|
+ * error rate
|
|
+ */
|
|
+ iwl_force_rf_reset(priv);
|
|
+ }
|
|
+ }
|
|
+
|
|
memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
|
|
|
|
set_bit(STATUS_STATISTICS, &priv->status);
|