linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/16] iwlwifi driver updates 07/08/2009
@ 2009-08-07 22:41 Reinette Chatre
  2009-08-07 22:41 ` [PATCH 01/16] iwlwifi: re-introduce per device debugging Reinette Chatre
                   ` (15 more replies)
  0 siblings, 16 replies; 22+ messages in thread
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Reinette Chatre

In this series we re-enable the feature that enables users with multiple
iwlwifi devices in one system to be able to set debug flags per device. We
also complete the "fat" to "ht40" name change. This series contains a few
patches that introduce significant debug support via debugfs. A previous
feature that attempted to make ucode loading more reliable caused some
issues and we are reverting it in this batch. We include a few fixes and
cleanup to the thermal throttling code and some other general fixes. A new
feature introduced with this series is the support of dynamic power save
support. Unfortuantely power save support still has some issues and we have
to disable it until these have been resolved.

[PATCH 01/16] iwlwifi: re-introduce per device debugging
[PATCH 02/16] iwlwifi: name changed from "fat" to "ht40"
[PATCH 03/16] iwlwifi: new debugging feature for dumping data traffic
[PATCH 04/16] iwlwifi: Traffic type and counter for debugFs
[PATCH 05/16] iwlwifi: tx/rx queue pointer information
[PATCH 06/16] iwlwifi: uCode statistics notification counter
[PATCH 07/16] iwlwifi: Display sensitivity and chain noise information
[PATCH 08/16] iwlwifi: revert uCode Alive notification with timeout
[PATCH 09/16] iwlwifi: fix thermal throttling locking problem
[PATCH 10/16] iwlwifi: fix legacy thermal throttling power index
[PATCH 11/16] iwlwifi: handle the case when set power fail
[PATCH 12/16] iwlwifi: refactor some thermal throttle code
[PATCH 13/16] iwlwifi: fix missing EXPORT_SYMBOL
[PATCH 14/16] iwlwifi: display correct critical temperature infomation
[PATCH 15/16] iwlwifi: automatically adjust sleep level
[PATCH 16/16] iwlwifi: disable powersave mode


Thank you

Reinette


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 01/16] iwlwifi: re-introduce per device debugging
  2009-08-07 22:41 [PATCH 0/16] iwlwifi driver updates 07/08/2009 Reinette Chatre
@ 2009-08-07 22:41 ` Reinette Chatre
  2009-08-07 22:41 ` [PATCH 02/16] iwlwifi: name changed from "fat" to "ht40" Reinette Chatre
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Reinette Chatre

From: Reinette Chatre <reinette.chatre@intel.com>

Commit "iwlwifi: make debug level more user friendly" cleaned up the
debug level handling. In doing so it created a single global debug
level for all devices. Some setups do consits of more that one iwlwifi
device and in these setups there is a requirement that debug levels
should be unique per device.

We now re-introduce the per device debugging while maintaining the
cleanup effort of the previous patch.

The maintain the global debug level and now introduce a per-device debug
level that will be used if it (the per-device debug level) is set. The
per-device debug level can be controlled via the debug_level sysfs file
while the global debug level is controlled by the debug module parameter.

Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Acked-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-3945.c     |    4 ++--
 drivers/net/wireless/iwlwifi/iwl-4965.c     |    4 ++--
 drivers/net/wireless/iwlwifi/iwl-agn.c      |   22 +++++++++++-----------
 drivers/net/wireless/iwlwifi/iwl-core.c     |    8 ++++----
 drivers/net/wireless/iwlwifi/iwl-debug.h    |   11 ++++++-----
 drivers/net/wireless/iwlwifi/iwl-dev.h      |   21 +++++++++++++++++++++
 drivers/net/wireless/iwlwifi/iwl-rx.c       |    6 +++---
 drivers/net/wireless/iwlwifi/iwl-sta.c      |    2 +-
 drivers/net/wireless/iwlwifi/iwl-tx.c       |    4 ++--
 drivers/net/wireless/iwlwifi/iwl3945-base.c |   21 +++++++++++----------
 10 files changed, 63 insertions(+), 40 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index e1b0ef3..7ad0207 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -502,14 +502,14 @@ static void _iwl3945_dbg_report_frame(struct iwl_priv *priv,
 		}
 	}
 	if (print_dump)
-		iwl_print_hex_dump(IWL_DL_RX, data, length);
+		iwl_print_hex_dump(priv, IWL_DL_RX, data, length);
 }
 
 static void iwl3945_dbg_report_frame(struct iwl_priv *priv,
 		      struct iwl_rx_packet *pkt,
 		      struct ieee80211_hdr *header, int group100)
 {
-	if (iwl_debug_level & IWL_DL_RX)
+	if (iwl_get_debug_level(priv) & IWL_DL_RX)
 		_iwl3945_dbg_report_frame(priv, pkt, header, group100);
 }
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 6702148..62436a9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -46,7 +46,7 @@
 #include "iwl-sta.h"
 
 static int iwl4965_send_tx_power(struct iwl_priv *priv);
-static int iwl4965_hw_get_temperature(const struct iwl_priv *priv);
+static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
 
 /* Highest firmware API version supported */
 #define IWL4965_UCODE_API_MAX 2
@@ -1680,7 +1680,7 @@ static s32 sign_extend(u32 oper, int index)
  *
  * A return of <0 indicates bogus data in the statistics
  */
-static int iwl4965_hw_get_temperature(const struct iwl_priv *priv)
+static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
 {
 	s32 temperature;
 	s32 vt;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index db580cb..24c1ae6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -896,7 +896,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
 	iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_debug_level & IWL_DL_ISR) {
+	if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
 		/* just for debug */
 		inta_mask = iwl_read32(priv, CSR_INT_MASK);
 		IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
@@ -931,7 +931,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
 	}
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_debug_level & (IWL_DL_ISR)) {
+	if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
 		/* NIC fires this, but we don't use it, redundant with WAKEUP */
 		if (inta & CSR_INT_BIT_SCD) {
 			IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
@@ -1045,7 +1045,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
 		iwl_enable_interrupts(priv);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_debug_level & (IWL_DL_ISR)) {
+	if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
 		inta = iwl_read32(priv, CSR_INT);
 		inta_mask = iwl_read32(priv, CSR_INT_MASK);
 		inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
@@ -1076,7 +1076,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
 	inta = priv->inta;
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_debug_level & IWL_DL_ISR) {
+	if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
 		/* just for debug */
 		inta_mask = iwl_read32(priv, CSR_INT_MASK);
 		IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ",
@@ -1104,7 +1104,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
 	}
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_debug_level & (IWL_DL_ISR)) {
+	if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
 		/* NIC fires this, but we don't use it, redundant with WAKEUP */
 		if (inta & CSR_INT_BIT_SCD) {
 			IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
@@ -2455,15 +2455,15 @@ static int iwl_mac_get_stats(struct ieee80211_hw *hw,
  *
  * See the level definitions in iwl for details.
  *
- * FIXME This file can be deprecated as the module parameter is
- * writable and users can thus also change the debug level
- * using the /sys/module/iwl3945/parameters/debug file.
+ * The debug_level being managed using sysfs below is a per device debug
+ * level that is used instead of the global debug level if it (the per
+ * device debug level) is set.
  */
-
 static ssize_t show_debug_level(struct device *d,
 				struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "0x%08X\n", iwl_debug_level);
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
 }
 static ssize_t store_debug_level(struct device *d,
 				struct device_attribute *attr,
@@ -2477,7 +2477,7 @@ static ssize_t store_debug_level(struct device *d,
 	if (ret)
 		IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
 	else
-		iwl_debug_level = val;
+		priv->debug_level = val;
 
 	return strnlen(buf, count);
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 2ffbd27..30f1953 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1278,7 +1278,7 @@ static void iwl_print_rx_config_cmd(struct iwl_priv *priv)
 	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
 
 	IWL_DEBUG_RADIO(priv, "RX CONFIG:\n");
-	iwl_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
+	iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
 	IWL_DEBUG_RADIO(priv, "u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
 	IWL_DEBUG_RADIO(priv, "u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
 	IWL_DEBUG_RADIO(priv, "u32 filter_flags: 0x%08x\n",
@@ -1508,7 +1508,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
 	clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_debug_level & IWL_DL_FW_ERRORS) {
+	if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) {
 		iwl_dump_nic_error_log(priv);
 		iwl_dump_nic_event_log(priv);
 		iwl_print_rx_config_cmd(priv);
@@ -1985,7 +1985,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
 	}
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_debug_level & (IWL_DL_ISR)) {
+	if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
 		inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
 		IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, "
 			      "fh 0x%08x\n", inta, inta_mask, inta_fh);
@@ -2310,7 +2310,7 @@ void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
 	IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
 			"notification for %s:\n",
 			le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
-	iwl_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
+	iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
 }
 EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif);
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index fbe1776..09af046 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -46,7 +46,7 @@ do {									\
 #ifdef CONFIG_IWLWIFI_DEBUG
 #define IWL_DEBUG(__priv, level, fmt, args...)				\
 do {									\
-	if (iwl_debug_level & (level))					\
+	if (iwl_get_debug_level(__priv) & (level))					\
 		dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev),		\
 			 "%c %s " fmt, in_interrupt() ? 'I' : 'U',	\
 			__func__ , ## args);				\
@@ -54,15 +54,15 @@ do {									\
 
 #define IWL_DEBUG_LIMIT(__priv, level, fmt, args...)			\
 do {									\
-	if ((iwl_debug_level & (level)) && net_ratelimit())		\
+	if ((iwl_get_debug_level(__priv) & (level)) && net_ratelimit())		\
 		dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev),		\
 			"%c %s " fmt, in_interrupt() ? 'I' : 'U',	\
 			 __func__ , ## args);				\
 } while (0)
 
-#define iwl_print_hex_dump(level, p, len) 				\
+#define iwl_print_hex_dump(priv, level, p, len) 			\
 do {                                            			\
-	if (iwl_debug_level & level)          				\
+	if (iwl_get_debug_level(priv) & level) 				\
 		print_hex_dump(KERN_DEBUG, "iwl data: ",		\
 			       DUMP_PREFIX_OFFSET, 16, 1, p, len, 1);	\
 } while (0)
@@ -106,7 +106,8 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv);
 #else
 #define IWL_DEBUG(__priv, level, fmt, args...)
 #define IWL_DEBUG_LIMIT(__priv, level, fmt, args...)
-static inline void iwl_print_hex_dump(int level, void *p, u32 len)
+static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,
+				      void *p, u32 len)
 {}
 #endif				/* CONFIG_IWLWIFI_DEBUG */
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index cab6255..1bf3e4c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1175,6 +1175,8 @@ struct iwl_priv {
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 	/* debugging info */
+	u32 debug_level; /* per device debugging will override global
+			    iwl_debug_level if set */
 	u32 framecnt_to_us;
 	atomic_t restrict_refcnt;
 	bool disable_ht40;
@@ -1211,8 +1213,27 @@ static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id)
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 const char *iwl_get_tx_fail_reason(u32 status);
+/*
+ * iwl_get_debug_level: Return active debug level for device
+ *
+ * Using sysfs it is possible to set per device debug level. This debug
+ * level will be used if set, otherwise the global debug level which can be
+ * set via module parameter is used.
+ */
+static inline u32 iwl_get_debug_level(struct iwl_priv *priv)
+{
+	if (priv->debug_level)
+		return priv->debug_level;
+	else
+		return iwl_debug_level;
+}
 #else
 static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; }
+
+static inline u32 iwl_get_debug_level(struct iwl_priv *priv)
+{
+	return iwl_debug_level;
+}
 #endif
 
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index e002c8b..98f0142 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -645,7 +645,7 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv,
 	u32 tsf_low;
 	int rssi;
 
-	if (likely(!(iwl_debug_level & IWL_DL_RX)))
+	if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX)))
 		return;
 
 	/* MAC header */
@@ -741,7 +741,7 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv,
 		}
 	}
 	if (print_dump)
-		iwl_print_hex_dump(IWL_DL_RX, header, length);
+		iwl_print_hex_dump(priv, IWL_DL_RX, header, length);
 }
 #endif
 
@@ -1060,7 +1060,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
 
 	/* Set "1" to report good data frames in groups of 100 */
 #ifdef CONFIG_IWLWIFI_DEBUG
-	if (unlikely(iwl_debug_level & IWL_DL_RX))
+	if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX))
 		iwl_dbg_report_frame(priv, rx_start, len, header, 1);
 #endif
 	IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n",
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index efcae0d..def1254 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -1088,7 +1088,7 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
 		IWL_DEBUG_DROP(priv, "Station %pM not in station map. "
 			       "Defaulting to broadcast...\n",
 			       hdr->addr1);
-		iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
+		iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
 		return priv->hw_params.bcast_sta_id;
 
 	default:
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 288b871..0cac06c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -884,8 +884,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 	IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n",
 		     le16_to_cpu(out_cmd->hdr.sequence));
 	IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags));
-	iwl_print_hex_dump(IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
-	iwl_print_hex_dump(IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
+	iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
+	iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
 
 	/* Set up entry for this TFD in Tx byte-count array */
 	if (info->flags & IEEE80211_TX_CTL_AMPDU)
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index ea051b7..0babce2 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -614,8 +614,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 	IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n",
 		     le16_to_cpu(out_cmd->hdr.sequence));
 	IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx->tx_flags));
-	iwl_print_hex_dump(IWL_DL_TX, tx, sizeof(*tx));
-	iwl_print_hex_dump(IWL_DL_TX, (u8 *)tx->hdr,
+	iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx));
+	iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr,
 			   ieee80211_hdrlen(fc));
 
 	/*
@@ -1646,7 +1646,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
 	iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_debug_level & IWL_DL_ISR) {
+	if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
 		/* just for debug */
 		inta_mask = iwl_read32(priv, CSR_INT_MASK);
 		IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
@@ -1681,7 +1681,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
 	}
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_debug_level & (IWL_DL_ISR)) {
+	if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
 		/* NIC fires this, but we don't use it, redundant with WAKEUP */
 		if (inta & CSR_INT_BIT_SCD) {
 			IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
@@ -1760,7 +1760,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
 		iwl_enable_interrupts(priv);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_debug_level & (IWL_DL_ISR)) {
+	if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
 		inta = iwl_read32(priv, CSR_INT);
 		inta_mask = iwl_read32(priv, CSR_INT_MASK);
 		inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
@@ -3311,14 +3311,15 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
  *
  * See the level definitions in iwl for details.
  *
- * FIXME This file can be deprecated as the module parameter is
- * writable and users can thus also change the debug level
- * using the /sys/module/iwl3945/parameters/debug file.
+ * The debug_level being managed using sysfs below is a per device debug
+ * level that is used instead of the global debug level if it (the per
+ * device debug level) is set.
  */
 static ssize_t show_debug_level(struct device *d,
 				struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "0x%08X\n", iwl_debug_level);
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
 }
 static ssize_t store_debug_level(struct device *d,
 				struct device_attribute *attr,
@@ -3332,7 +3333,7 @@ static ssize_t store_debug_level(struct device *d,
 	if (ret)
 		IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf);
 	else
-		iwl_debug_level = val;
+		priv->debug_level = val;
 
 	return strnlen(buf, count);
 }
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 02/16] iwlwifi: name changed from "fat" to "ht40"
  2009-08-07 22:41 [PATCH 0/16] iwlwifi driver updates 07/08/2009 Reinette Chatre
  2009-08-07 22:41 ` [PATCH 01/16] iwlwifi: re-introduce per device debugging Reinette Chatre
@ 2009-08-07 22:41 ` Reinette Chatre
  2009-08-07 22:41 ` [PATCH 03/16] iwlwifi: new debugging feature for dumping data traffic Reinette Chatre
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

Rename "fat" to "ht40"
The term "fat channel" is deprecated in favor of "HT40"

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-1000.c     |    4 +-
 drivers/net/wireless/iwlwifi/iwl-3945-hw.h  |    2 +-
 drivers/net/wireless/iwlwifi/iwl-3945.c     |    4 +-
 drivers/net/wireless/iwlwifi/iwl-4965-hw.h  |    6 +-
 drivers/net/wireless/iwlwifi/iwl-4965.c     |   42 ++++++++--------
 drivers/net/wireless/iwlwifi/iwl-5000.c     |   10 ++--
 drivers/net/wireless/iwlwifi/iwl-6000.c     |    4 +-
 drivers/net/wireless/iwlwifi/iwl-agn-rs.c   |   67 ++++++++++++++-------------
 drivers/net/wireless/iwlwifi/iwl-commands.h |   22 ++++----
 drivers/net/wireless/iwlwifi/iwl-core.c     |   24 +++++-----
 drivers/net/wireless/iwlwifi/iwl-core.h     |    2 +-
 drivers/net/wireless/iwlwifi/iwl-dev.h      |   22 ++++----
 drivers/net/wireless/iwlwifi/iwl-eeprom.c   |   54 +++++++++++-----------
 drivers/net/wireless/iwlwifi/iwl-eeprom.h   |   34 +++++++-------
 drivers/net/wireless/iwlwifi/iwl-power.c    |    2 +-
 drivers/net/wireless/iwlwifi/iwl-rx.c       |    4 +-
 drivers/net/wireless/iwlwifi/iwl-sta.c      |    6 +-
 17 files changed, 155 insertions(+), 154 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index cf3fbc6..191718a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -117,8 +117,8 @@ static struct iwl_lib_ops iwl1000_lib = {
 			EEPROM_5000_REG_BAND_3_CHANNELS,
 			EEPROM_5000_REG_BAND_4_CHANNELS,
 			EEPROM_5000_REG_BAND_5_CHANNELS,
-			EEPROM_5000_REG_BAND_24_FAT_CHANNELS,
-			EEPROM_5000_REG_BAND_52_FAT_CHANNELS
+			EEPROM_5000_REG_BAND_24_HT40_CHANNELS,
+			EEPROM_5000_REG_BAND_52_HT40_CHANNELS
 		},
 		.verify_signature  = iwlcore_eeprom_verify_signature,
 		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
index b569c6f..1677278 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
@@ -176,7 +176,7 @@ struct iwl3945_eeprom {
  * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
  * txpower (MSB).
  *
- * Entries immediately below are for 20 MHz channel width.  FAT (40 MHz)
+ * Entries immediately below are for 20 MHz channel width.  HT40 (40 MHz)
  * channels (only for 4965, not supported by 3945) appear later in the EEPROM.
  *
  * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 7ad0207..9e33507 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -2851,8 +2851,8 @@ static struct iwl_lib_ops iwl3945_lib = {
 			EEPROM_REGULATORY_BAND_3_CHANNELS,
 			EEPROM_REGULATORY_BAND_4_CHANNELS,
 			EEPROM_REGULATORY_BAND_5_CHANNELS,
-			EEPROM_REGULATORY_BAND_NO_FAT,
-			EEPROM_REGULATORY_BAND_NO_FAT,
+			EEPROM_REGULATORY_BAND_NO_HT40,
+			EEPROM_REGULATORY_BAND_NO_HT40,
 		},
 		.verify_signature  = iwlcore_eeprom_verify_signature,
 		.acquire_semaphore = iwl3945_eeprom_acquire_semaphore,
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
index a71a489..b34322a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
@@ -188,7 +188,7 @@ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
  *
  * 1)  Regulatory information (max txpower and channel usage flags) is provided
  *     separately for each channel that can possibly supported by 4965.
- *     40 MHz wide (.11n fat) channels are listed separately from 20 MHz
+ *     40 MHz wide (.11n HT40) channels are listed separately from 20 MHz
  *     (legacy) channels.
  *
  *     See struct iwl4965_eeprom_channel for format, and struct iwl4965_eeprom
@@ -251,8 +251,8 @@ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
  *     no reduction (such as with regulatory txpower limits) is required.
  *
  *     Saturation and Backoff values apply equally to 20 Mhz (legacy) channel
- *     widths and 40 Mhz (.11n fat) channel widths; there is no separate
- *     factory measurement for fat channels.
+ *     widths and 40 Mhz (.11n HT40) channel widths; there is no separate
+ *     factory measurement for ht40 channels.
  *
  *     The result of this step is the final target txpower.  The rest of
  *     the steps figure out the proper settings for the device to achieve
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 62436a9..f02023e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -317,7 +317,7 @@ restart:
 	queue_work(priv->workqueue, &priv->restart);
 }
 
-static bool is_fat_channel(__le32 rxon_flags)
+static bool is_ht40_channel(__le32 rxon_flags)
 {
 	int chan_mod = le32_to_cpu(rxon_flags & RXON_FLG_CHANNEL_MODE_MSK)
 				    >> RXON_FLG_CHANNEL_MODE_POS;
@@ -806,7 +806,7 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
 	priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE;
 	priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE;
 	priv->hw_params.max_bsm_size = BSM_SRAM_SIZE;
-	priv->hw_params.fat_channel = BIT(IEEE80211_BAND_5GHZ);
+	priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_5GHZ);
 
 	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
 
@@ -1266,7 +1266,7 @@ static const struct gain_entry gain_table[2][108] = {
 };
 
 static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
-				    u8 is_fat, u8 ctrl_chan_high,
+				    u8 is_ht40, u8 ctrl_chan_high,
 				    struct iwl4965_tx_power_db *tx_power_tbl)
 {
 	u8 saturation_power;
@@ -1298,8 +1298,8 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
 	user_target_power = 2 * priv->tx_power_user_lmt;
 
 	/* Get current (RXON) channel, band, width */
-	IWL_DEBUG_TXPOWER(priv, "chan %d band %d is_fat %d\n", channel, band,
-			  is_fat);
+	IWL_DEBUG_TXPOWER(priv, "chan %d band %d is_ht40 %d\n", channel, band,
+			  is_ht40);
 
 	ch_info = iwl_get_channel_info(priv, priv->band, channel);
 
@@ -1318,7 +1318,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
 	IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n",
 			  channel, txatten_grp);
 
-	if (is_fat) {
+	if (is_ht40) {
 		if (ctrl_chan_high)
 			channel -= 2;
 		else
@@ -1342,8 +1342,8 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
 
 	/* regulatory txpower limits ... reg_limit values are in half-dBm,
 	 *   max_power_avg values are in dBm, convert * 2 */
-	if (is_fat)
-		reg_limit = ch_info->fat_max_power_avg * 2;
+	if (is_ht40)
+		reg_limit = ch_info->ht40_max_power_avg * 2;
 	else
 		reg_limit = ch_info->max_power_avg * 2;
 
@@ -1509,7 +1509,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
 /**
  * iwl4965_send_tx_power - Configure the TXPOWER level user limit
  *
- * Uses the active RXON for channel, band, and characteristics (fat, high)
+ * Uses the active RXON for channel, band, and characteristics (ht40, high)
  * The power limit is taken from priv->tx_power_user_lmt.
  */
 static int iwl4965_send_tx_power(struct iwl_priv *priv)
@@ -1517,7 +1517,7 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
 	struct iwl4965_txpowertable_cmd cmd = { 0 };
 	int ret;
 	u8 band = 0;
-	bool is_fat = false;
+	bool is_ht40 = false;
 	u8 ctrl_chan_high = 0;
 
 	if (test_bit(STATUS_SCANNING, &priv->status)) {
@@ -1530,9 +1530,9 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
 
 	band = priv->band == IEEE80211_BAND_2GHZ;
 
-	is_fat =  is_fat_channel(priv->active_rxon.flags);
+	is_ht40 =  is_ht40_channel(priv->active_rxon.flags);
 
-	if (is_fat &&
+	if (is_ht40 &&
 	    (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
 		ctrl_chan_high = 1;
 
@@ -1541,7 +1541,7 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
 
 	ret = iwl4965_fill_txpower_tbl(priv, band,
 				le16_to_cpu(priv->active_rxon.channel),
-				is_fat, ctrl_chan_high, &cmd.tx_power);
+				is_ht40, ctrl_chan_high, &cmd.tx_power);
 	if (ret)
 		goto out;
 
@@ -1595,7 +1595,7 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
 {
 	int rc;
 	u8 band = 0;
-	bool is_fat = false;
+	bool is_ht40 = false;
 	u8 ctrl_chan_high = 0;
 	struct iwl4965_channel_switch_cmd cmd = { 0 };
 	const struct iwl_channel_info *ch_info;
@@ -1604,9 +1604,9 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
 
 	ch_info = iwl_get_channel_info(priv, priv->band, channel);
 
-	is_fat = is_fat_channel(priv->staging_rxon.flags);
+	is_ht40 = is_ht40_channel(priv->staging_rxon.flags);
 
-	if (is_fat &&
+	if (is_ht40 &&
 	    (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
 		ctrl_chan_high = 1;
 
@@ -1621,7 +1621,7 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
 	else
 		cmd.expect_beacon = 1;
 
-	rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_fat,
+	rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40,
 				      ctrl_chan_high, &cmd.tx_power);
 	if (rc) {
 		IWL_DEBUG_11H(priv, "error:%d  fill txpower_tbl\n", rc);
@@ -1688,8 +1688,8 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
 	u32 R4;
 
 	if (test_bit(STATUS_TEMPERATURE, &priv->status) &&
-		(priv->statistics.flag & STATISTICS_REPLY_FLG_FAT_MODE_MSK)) {
-		IWL_DEBUG_TEMP(priv, "Running FAT temperature calibration\n");
+		(priv->statistics.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
+		IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n");
 		R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]);
 		R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]);
 		R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[1]);
@@ -2330,8 +2330,8 @@ static struct iwl_lib_ops iwl4965_lib = {
 			EEPROM_REGULATORY_BAND_3_CHANNELS,
 			EEPROM_REGULATORY_BAND_4_CHANNELS,
 			EEPROM_REGULATORY_BAND_5_CHANNELS,
-			EEPROM_4965_REGULATORY_BAND_24_FAT_CHANNELS,
-			EEPROM_4965_REGULATORY_BAND_52_FAT_CHANNELS
+			EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS,
+			EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS
 		},
 		.verify_signature  = iwlcore_eeprom_verify_signature,
 		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 87957c0..755c184 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -845,7 +845,7 @@ int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
 	}
 
 	priv->hw_params.max_bsm_size = 0;
-	priv->hw_params.fat_channel =  BIT(IEEE80211_BAND_2GHZ) |
+	priv->hw_params.ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
 					BIT(IEEE80211_BAND_5GHZ);
 	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
 
@@ -1547,8 +1547,8 @@ struct iwl_lib_ops iwl5000_lib = {
 			EEPROM_5000_REG_BAND_3_CHANNELS,
 			EEPROM_5000_REG_BAND_4_CHANNELS,
 			EEPROM_5000_REG_BAND_5_CHANNELS,
-			EEPROM_5000_REG_BAND_24_FAT_CHANNELS,
-			EEPROM_5000_REG_BAND_52_FAT_CHANNELS
+			EEPROM_5000_REG_BAND_24_HT40_CHANNELS,
+			EEPROM_5000_REG_BAND_52_HT40_CHANNELS
 		},
 		.verify_signature  = iwlcore_eeprom_verify_signature,
 		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
@@ -1597,8 +1597,8 @@ static struct iwl_lib_ops iwl5150_lib = {
 			EEPROM_5000_REG_BAND_3_CHANNELS,
 			EEPROM_5000_REG_BAND_4_CHANNELS,
 			EEPROM_5000_REG_BAND_5_CHANNELS,
-			EEPROM_5000_REG_BAND_24_FAT_CHANNELS,
-			EEPROM_5000_REG_BAND_52_FAT_CHANNELS
+			EEPROM_5000_REG_BAND_24_HT40_CHANNELS,
+			EEPROM_5000_REG_BAND_52_HT40_CHANNELS
 		},
 		.verify_signature  = iwlcore_eeprom_verify_signature,
 		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 4450943..c3ec6c2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -118,8 +118,8 @@ static struct iwl_lib_ops iwl6000_lib = {
 			EEPROM_5000_REG_BAND_3_CHANNELS,
 			EEPROM_5000_REG_BAND_4_CHANNELS,
 			EEPROM_5000_REG_BAND_5_CHANNELS,
-			EEPROM_5000_REG_BAND_24_FAT_CHANNELS,
-			EEPROM_5000_REG_BAND_52_FAT_CHANNELS
+			EEPROM_5000_REG_BAND_24_HT40_CHANNELS,
+			EEPROM_5000_REG_BAND_52_HT40_CHANNELS
 		},
 		.verify_signature  = iwlcore_eeprom_verify_signature,
 		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 52a4810..0c3ed23 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -97,7 +97,7 @@ struct iwl_scale_tbl_info {
 	enum iwl_table_type lq_type;
 	u8 ant_type;
 	u8 is_SGI;	/* 1 = short guard interval */
-	u8 is_fat;	/* 1 = 40 MHz channel width */
+	u8 is_ht40;	/* 1 = 40 MHz channel width */
 	u8 is_dup;	/* 1 = duplicated data streams */
 	u8 action;	/* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */
 	u8 max_search;	/* maximun number of tables we can search */
@@ -539,11 +539,11 @@ static u32 rate_n_flags_from_tbl(struct iwl_priv *priv,
 						     RATE_MCS_ANT_ABC_MSK);
 
 	if (is_Ht(tbl->lq_type)) {
-		if (tbl->is_fat) {
+		if (tbl->is_ht40) {
 			if (tbl->is_dup)
 				rate_n_flags |= RATE_MCS_DUP_MSK;
 			else
-				rate_n_flags |= RATE_MCS_FAT_MSK;
+				rate_n_flags |= RATE_MCS_HT40_MSK;
 		}
 		if (tbl->is_SGI)
 			rate_n_flags |= RATE_MCS_SGI_MSK;
@@ -579,7 +579,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
 		return -EINVAL;
 	}
 	tbl->is_SGI = 0;	/* default legacy setup */
-	tbl->is_fat = 0;
+	tbl->is_ht40 = 0;
 	tbl->is_dup = 0;
 	tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS);
 	tbl->lq_type = LQ_NONE;
@@ -598,9 +598,9 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
 		if (rate_n_flags & RATE_MCS_SGI_MSK)
 			tbl->is_SGI = 1;
 
-		if ((rate_n_flags & RATE_MCS_FAT_MSK) ||
+		if ((rate_n_flags & RATE_MCS_HT40_MSK) ||
 		    (rate_n_flags & RATE_MCS_DUP_MSK))
-			tbl->is_fat = 1;
+			tbl->is_ht40 = 1;
 
 		if (rate_n_flags & RATE_MCS_DUP_MSK)
 			tbl->is_dup = 1;
@@ -776,7 +776,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
 		if (num_of_ant(tbl->ant_type) > 1)
 			tbl->ant_type = ANT_A;/*FIXME:RS*/
 
-		tbl->is_fat = 0;
+		tbl->is_ht40 = 0;
 		tbl->is_SGI = 0;
 		tbl->max_search = IWL_MAX_SEARCH;
 	}
@@ -880,7 +880,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
 
 	if ((info->status.rates[0].idx < 0) ||
 	    (tbl_type.is_SGI != !!(info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)) ||
-	    (tbl_type.is_fat != !!(info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) ||
+	    (tbl_type.is_ht40 != !!(info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) ||
 	    (tbl_type.is_dup != !!(info->status.rates[0].flags & IEEE80211_TX_RC_DUP_DATA)) ||
 	    (tbl_type.ant_type != info->antenna_sel_tx) ||
 	    (!!(tx_rate & RATE_MCS_HT_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) ||
@@ -1049,7 +1049,7 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
 		else
 			tbl->expected_tpt = expected_tpt_A;
 	} else if (is_siso(tbl->lq_type)) {
-		if (tbl->is_fat && !lq_sta->is_dup)
+		if (tbl->is_ht40 && !lq_sta->is_dup)
 			if (tbl->is_SGI)
 				tbl->expected_tpt = expected_tpt_siso40MHzSGI;
 			else
@@ -1059,7 +1059,7 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
 		else
 			tbl->expected_tpt = expected_tpt_siso20MHz;
 	} else if (is_mimo2(tbl->lq_type)) {
-		if (tbl->is_fat && !lq_sta->is_dup)
+		if (tbl->is_ht40 && !lq_sta->is_dup)
 			if (tbl->is_SGI)
 				tbl->expected_tpt = expected_tpt_mimo2_40MHzSGI;
 			else
@@ -1069,7 +1069,7 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
 		else
 			tbl->expected_tpt = expected_tpt_mimo2_20MHz;
 	} else if (is_mimo3(tbl->lq_type)) {
-		if (tbl->is_fat && !lq_sta->is_dup)
+		if (tbl->is_ht40 && !lq_sta->is_dup)
 			if (tbl->is_SGI)
 				tbl->expected_tpt = expected_tpt_mimo3_40MHzSGI;
 			else
@@ -1217,13 +1217,13 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
 	tbl->max_search = IWL_MAX_SEARCH;
 	rate_mask = lq_sta->active_mimo2_rate;
 
-	if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap))
-		tbl->is_fat = 1;
+	if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap))
+		tbl->is_ht40 = 1;
 	else
-		tbl->is_fat = 0;
+		tbl->is_ht40 = 0;
 
 	/* FIXME: - don't toggle SGI here
-	if (tbl->is_fat) {
+	if (tbl->is_ht40) {
 		if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
 			tbl->is_SGI = 1;
 		else
@@ -1283,13 +1283,13 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
 	tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH;
 	rate_mask = lq_sta->active_mimo3_rate;
 
-	if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap))
-		tbl->is_fat = 1;
+	if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap))
+		tbl->is_ht40 = 1;
 	else
-		tbl->is_fat = 0;
+		tbl->is_ht40 = 0;
 
 	/* FIXME: - don't toggle SGI here
-	if (tbl->is_fat) {
+	if (tbl->is_ht40) {
 		if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
 			tbl->is_SGI = 1;
 		else
@@ -1342,13 +1342,13 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
 	tbl->max_search = IWL_MAX_SEARCH;
 	rate_mask = lq_sta->active_siso_rate;
 
-	if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap))
-		tbl->is_fat = 1;
+	if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap))
+		tbl->is_ht40 = 1;
 	else
-		tbl->is_fat = 0;
+		tbl->is_ht40 = 0;
 
 	/* FIXME: - don't toggle SGI here
-	if (tbl->is_fat) {
+	if (tbl->is_ht40) {
 		if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
 			tbl->is_SGI = 1;
 		else
@@ -1586,11 +1586,11 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
 				goto out;
 			break;
 		case IWL_SISO_SWITCH_GI:
-			if (!tbl->is_fat &&
+			if (!tbl->is_ht40 &&
 				!(priv->current_ht_config.sgf &
 						HT_SHORT_GI_20MHZ))
 				break;
-			if (tbl->is_fat &&
+			if (tbl->is_ht40 &&
 				!(priv->current_ht_config.sgf &
 						HT_SHORT_GI_40MHZ))
 				break;
@@ -1726,11 +1726,11 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
 			break;
 
 		case IWL_MIMO2_SWITCH_GI:
-			if (!tbl->is_fat &&
+			if (!tbl->is_ht40 &&
 				!(priv->current_ht_config.sgf &
 						HT_SHORT_GI_20MHZ))
 				break;
-			if (tbl->is_fat &&
+			if (tbl->is_ht40 &&
 				!(priv->current_ht_config.sgf &
 						HT_SHORT_GI_40MHZ))
 				break;
@@ -1890,11 +1890,11 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
 			break;
 
 		case IWL_MIMO3_SWITCH_GI:
-			if (!tbl->is_fat &&
+			if (!tbl->is_ht40 &&
 				!(priv->current_ht_config.sgf &
 						HT_SHORT_GI_20MHZ))
 				break;
-			if (tbl->is_fat &&
+			if (tbl->is_ht40 &&
 				!(priv->current_ht_config.sgf &
 						HT_SHORT_GI_40MHZ))
 				break;
@@ -2576,7 +2576,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
 			info->control.rates[0].flags |= IEEE80211_TX_RC_SHORT_GI;
 		if (lq_sta->last_rate_n_flags & RATE_MCS_DUP_MSK)
 			info->control.rates[0].flags |= IEEE80211_TX_RC_DUP_DATA;
-		if (lq_sta->last_rate_n_flags & RATE_MCS_FAT_MSK)
+		if (lq_sta->last_rate_n_flags & RATE_MCS_HT40_MSK)
 			info->control.rates[0].flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
 		if (lq_sta->last_rate_n_flags & RATE_MCS_GF_MSK)
 			info->control.rates[0].flags |= IEEE80211_TX_RC_GREEN_FIELD;
@@ -2963,7 +2963,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
 		   (is_siso(tbl->lq_type)) ? "SISO" :
 		   ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3"));
 		   desc += sprintf(buff+desc, " %s",
-		   (tbl->is_fat) ? "40MHz" : "20MHz");
+		   (tbl->is_ht40) ? "40MHz" : "20MHz");
 		   desc += sprintf(buff+desc, " %s %s\n", (tbl->is_SGI) ? "SGI" : "",
 		   (lq_sta->is_green) ? "GF enabled" : "");
 	}
@@ -3028,12 +3028,13 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
 		return -ENOMEM;
 
 	for (i = 0; i < LQ_SIZE; i++) {
-		desc += sprintf(buff+desc, "%s type=%d SGI=%d FAT=%d DUP=%d GF=%d\n"
+		desc += sprintf(buff+desc,
+				"%s type=%d SGI=%d HT40=%d DUP=%d GF=%d\n"
 				"rate=0x%X\n",
 				lq_sta->active_tbl == i ? "*" : "x",
 				lq_sta->lq_info[i].lq_type,
 				lq_sta->lq_info[i].is_SGI,
-				lq_sta->lq_info[i].is_fat,
+				lq_sta->lq_info[i].is_ht40,
 				lq_sta->lq_info[i].is_dup,
 				lq_sta->is_green,
 				lq_sta->lq_info[i].current_rate);
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 39ede57..6188c54 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -283,7 +283,7 @@ struct iwl3945_power_per_rate {
  *        1)  Dual stream (MIMO)
  *        2)  Triple stream (MIMO)
  *
- *    5:  Value of 0x20 in bits 7:0 indicates 6 Mbps FAT duplicate data
+ *    5:  Value of 0x20 in bits 7:0 indicates 6 Mbps HT40 duplicate data
  *
  * Legacy OFDM rate format for bits 7:0 (bit 8 must be "0", bit 9 "0"):
  *  3-0:  0xD)   6 Mbps
@@ -320,11 +320,11 @@ struct iwl3945_power_per_rate {
 #define RATE_MCS_GF_POS 10
 #define RATE_MCS_GF_MSK 0x400
 
-/* Bit 11: (1) Use 40Mhz FAT chnl width, (0) use 20 MHz legacy chnl width */
-#define RATE_MCS_FAT_POS 11
-#define RATE_MCS_FAT_MSK 0x800
+/* Bit 11: (1) Use 40Mhz HT40 chnl width, (0) use 20 MHz legacy chnl width */
+#define RATE_MCS_HT40_POS 11
+#define RATE_MCS_HT40_MSK 0x800
 
-/* Bit 12: (1) Duplicate data on both 20MHz chnls.  FAT (bit 11) must be set. */
+/* Bit 12: (1) Duplicate data on both 20MHz chnls. HT40 (bit 11) must be set. */
 #define RATE_MCS_DUP_POS 12
 #define RATE_MCS_DUP_MSK 0x1000
 
@@ -459,7 +459,7 @@ struct iwl_init_alive_resp {
 
 	/* calibration values from "initialize" uCode */
 	__le32 voltage;		/* signed, higher value is lower voltage */
-	__le32 therm_r1[2];	/* signed, 1st for normal, 2nd for FAT channel*/
+	__le32 therm_r1[2];	/* signed, 1st for normal, 2nd for HT40 */
 	__le32 therm_r2[2];	/* signed */
 	__le32 therm_r3[2];	/* signed */
 	__le32 therm_r4[2];	/* signed */
@@ -610,7 +610,7 @@ enum {
 #define RXON_FLG_HT_OPERATING_MODE_POS		(23)
 
 #define RXON_FLG_HT_PROT_MSK			cpu_to_le32(0x1 << 23)
-#define RXON_FLG_FAT_PROT_MSK			cpu_to_le32(0x2 << 23)
+#define RXON_FLG_HT40_PROT_MSK			cpu_to_le32(0x2 << 23)
 
 #define RXON_FLG_CHANNEL_MODE_POS		(25)
 #define RXON_FLG_CHANNEL_MODE_MSK		cpu_to_le32(0x3 << 25)
@@ -891,7 +891,7 @@ struct iwl_qosparam_cmd {
 #define STA_FLG_AGG_MPDU_8US_MSK	cpu_to_le32(1 << 18)
 #define STA_FLG_MAX_AGG_SIZE_POS	(19)
 #define STA_FLG_MAX_AGG_SIZE_MSK	cpu_to_le32(3 << 19)
-#define STA_FLG_FAT_EN_MSK		cpu_to_le32(1 << 21)
+#define STA_FLG_HT40_EN_MSK		cpu_to_le32(1 << 21)
 #define STA_FLG_MIMO_DIS_MSK		cpu_to_le32(1 << 22)
 #define STA_FLG_AGG_MPDU_DENSITY_POS	(23)
 #define STA_FLG_AGG_MPDU_DENSITY_MSK	cpu_to_le32(7 << 23)
@@ -1984,10 +1984,10 @@ struct iwl_link_qual_agg_params {
  *     a) Use this same initial rate for first 3 entries.
  *     b) Find next lower available rate using same mode (SISO or MIMO),
  *        use for next 3 entries.  If no lower rate available, switch to
- *        legacy mode (no FAT channel, no MIMO, no short guard interval).
+ *        legacy mode (no HT40 channel, no MIMO, no short guard interval).
  *     c) If using MIMO, set command's mimo_delimiter to number of entries
  *        using MIMO (3 or 6).
- *     d) After trying 2 HT rates, switch to legacy mode (no FAT channel,
+ *     d) After trying 2 HT rates, switch to legacy mode (no HT40 channel,
  *        no MIMO, no short guard interval), at the next lower bit rate
  *        (e.g. if second HT bit rate was 54, try 48 legacy), and follow
  *        legacy procedure for remaining table entries.
@@ -3017,7 +3017,7 @@ struct iwl_statistics_cmd {
  * one channel that has just been scanned.
  */
 #define STATISTICS_REPLY_FLG_BAND_24G_MSK         cpu_to_le32(0x2)
-#define STATISTICS_REPLY_FLG_FAT_MODE_MSK         cpu_to_le32(0x8)
+#define STATISTICS_REPLY_FLG_HT40_MODE_MSK        cpu_to_le32(0x8)
 
 struct iwl3945_notif_statistics {
 	__le32 flag;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 30f1953..5315d34 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -105,7 +105,7 @@ void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
 		r->flags |= IEEE80211_TX_RC_MCS;
 	if (rate_n_flags & RATE_MCS_GF_MSK)
 		r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
-	if (rate_n_flags & RATE_MCS_FAT_MSK)
+	if (rate_n_flags & RATE_MCS_HT40_MSK)
 		r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
 	if (rate_n_flags & RATE_MCS_DUP_MSK)
 		r->flags |= IEEE80211_TX_RC_DUP_DATA;
@@ -400,7 +400,7 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
 			     (WLAN_HT_CAP_SM_PS_DISABLED << 2));
 
 	max_bit_rate = MAX_BIT_RATE_20_MHZ;
-	if (priv->hw_params.fat_channel & BIT(band)) {
+	if (priv->hw_params.ht40_channel & BIT(band)) {
 		ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
 		ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
 		ht_info->mcs.rx_mask[4] = 0x01;
@@ -540,7 +540,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
 			if (ch->flags & EEPROM_CHANNEL_RADAR)
 				geo_ch->flags |= IEEE80211_CHAN_RADAR;
 
-			geo_ch->flags |= ch->fat_extension_channel;
+			geo_ch->flags |= ch->ht40_extension_channel;
 
 			if (ch->max_power_avg > priv->tx_power_channel_lmt)
 				priv->tx_power_channel_lmt = ch->max_power_avg;
@@ -604,16 +604,16 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv,
 		return 0;
 
 	if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
-		return !(ch_info->fat_extension_channel &
+		return !(ch_info->ht40_extension_channel &
 					IEEE80211_CHAN_NO_HT40PLUS);
 	else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
-		return !(ch_info->fat_extension_channel &
+		return !(ch_info->ht40_extension_channel &
 					IEEE80211_CHAN_NO_HT40MINUS);
 
 	return 0;
 }
 
-u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
+u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
 			 struct ieee80211_sta_ht_cap *sta_ht_inf)
 {
 	struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
@@ -637,7 +637,7 @@ u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
 			le16_to_cpu(priv->staging_rxon.channel),
 			iwl_ht_conf->extension_chan_offset);
 }
-EXPORT_SYMBOL(iwl_is_fat_tx_allowed);
+EXPORT_SYMBOL(iwl_is_ht40_tx_allowed);
 
 static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
 {
@@ -866,7 +866,7 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
 	if (!ht_info->is_ht) {
 		rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
 			RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
-			RXON_FLG_FAT_PROT_MSK |
+			RXON_FLG_HT40_PROT_MSK |
 			RXON_FLG_HT_PROT_MSK);
 		return;
 	}
@@ -877,12 +877,12 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
 	rxon->flags |= cpu_to_le32(ht_info->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS);
 
 	/* Set up channel bandwidth:
-	 * 20 MHz only, 20/40 mixed or pure 40 if fat ok */
+	 * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */
 	/* clear the HT channel mode before set the mode */
 	rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
 			 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
-	if (iwl_is_fat_tx_allowed(priv, NULL)) {
-		/* pure 40 fat */
+	if (iwl_is_ht40_tx_allowed(priv, NULL)) {
+		/* pure ht40 */
 		if (ht_info->ht_protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {
 			rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40;
 			/* Note: control channel is opposite of extension channel */
@@ -2428,7 +2428,7 @@ static void iwl_ht_conf(struct iwl_priv *priv,
 	else if (conf_is_ht40_plus(&priv->hw->conf))
 		iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
 
-	/* If no above or below channel supplied disable FAT channel */
+	/* If no above or below channel supplied disable HT40 channel */
 	if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE &&
 	    iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW)
 		iwl_conf->supported_chan_width = 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 10ddcdd..dd66148 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -264,7 +264,7 @@ int iwl_full_rxon_required(struct iwl_priv *priv);
 void iwl_set_rxon_chain(struct iwl_priv *priv);
 int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
 void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info);
-u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
+u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
 			 struct ieee80211_sta_ht_cap *sta_ht_inf);
 void iwl_set_flags_for_band(struct iwl_priv *priv, enum ieee80211_band band);
 void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 1bf3e4c..624656a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -277,8 +277,8 @@ struct iwl_channel_info {
 	struct iwl4965_channel_tgd_info tgd;
 	struct iwl4965_channel_tgh_info tgh;
 	struct iwl_eeprom_channel eeprom;	/* EEPROM regulatory limit */
-	struct iwl_eeprom_channel fat_eeprom;	/* EEPROM regulatory limit for
-						 * FAT channel */
+	struct iwl_eeprom_channel ht40_eeprom;	/* EEPROM regulatory limit for
+						 * HT40 channel */
 
 	u8 channel;	  /* channel number */
 	u8 flags;	  /* flags copied from EEPROM */
@@ -291,13 +291,13 @@ struct iwl_channel_info {
 	u8 band_index;	  /* 0-4, maps channel to band1/2/3/4/5 */
 	enum ieee80211_band band;
 
-	/* FAT channel info */
-	s8 fat_max_power_avg;	/* (dBm) regul. eeprom, normal Tx, any rate */
-	s8 fat_curr_txpow;	/* (dBm) regulatory/spectrum/user (not h/w) */
-	s8 fat_min_power;	/* always 0 */
-	s8 fat_scan_power;	/* (dBm) eeprom, direct scans, any rate */
-	u8 fat_flags;		/* flags copied from EEPROM */
-	u8 fat_extension_channel; /* HT_IE_EXT_CHANNEL_* */
+	/* HT40 channel info */
+	s8 ht40_max_power_avg;	/* (dBm) regul. eeprom, normal Tx, any rate */
+	s8 ht40_curr_txpow;	/* (dBm) regulatory/spectrum/user (not h/w) */
+	s8 ht40_min_power;	/* always 0 */
+	s8 ht40_scan_power;	/* (dBm) eeprom, direct scans, any rate */
+	u8 ht40_flags;		/* flags copied from EEPROM */
+	u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */
 
 	/* Radio/DSP gain settings for each "normal" data Tx rate.
 	 * These include, in addition to RF and DSP gain, a few fields for
@@ -649,7 +649,7 @@ struct iwl_sensitivity_ranges {
  * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
  * @max_stations:
  * @bcast_sta_id:
- * @fat_channel: is 40MHz width possible in band 2.4
+ * @ht40_channel: is 40MHz width possible in band 2.4
  * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ)
  * @sw_crypto: 0 for hw, 1 for sw
  * @max_xxx_size: for ucode uses
@@ -673,7 +673,7 @@ struct iwl_hw_params {
 	u32 max_pkt_size;
 	u8  max_stations;
 	u8  bcast_sta_id;
-	u8 fat_channel;
+	u8  ht40_channel;
 	u8  max_beacon_itrvl;	/* in 1024 ms */
 	u32 max_inst_size;
 	u32 max_data_size;
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 51eed72..78c4a32 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -127,11 +127,11 @@ static const u8 iwl_eeprom_band_5[] = {	/* 5725-5825MHz */
 	145, 149, 153, 157, 161, 165
 };
 
-static const u8 iwl_eeprom_band_6[] = {       /* 2.4 FAT channel */
+static const u8 iwl_eeprom_band_6[] = {       /* 2.4 ht40 channel */
 	1, 2, 3, 4, 5, 6, 7
 };
 
-static const u8 iwl_eeprom_band_7[] = {       /* 5.2 FAT channel */
+static const u8 iwl_eeprom_band_7[] = {       /* 5.2 ht40 channel */
 	36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
 };
 
@@ -462,13 +462,13 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
 				iwl_eeprom_query_addr(priv, offset);
 		*eeprom_ch_index = iwl_eeprom_band_5;
 		break;
-	case 6:		/* 2.4GHz FAT channels */
+	case 6:		/* 2.4GHz ht40 channels */
 		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6);
 		*eeprom_ch_info = (struct iwl_eeprom_channel *)
 				iwl_eeprom_query_addr(priv, offset);
 		*eeprom_ch_index = iwl_eeprom_band_6;
 		break;
-	case 7:		/* 5 GHz FAT channels */
+	case 7:		/* 5 GHz ht40 channels */
 		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7);
 		*eeprom_ch_info = (struct iwl_eeprom_channel *)
 				iwl_eeprom_query_addr(priv, offset);
@@ -484,14 +484,14 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
 			    ? # x " " : "")
 
 /**
- * iwl_set_fat_chan_info - Copy fat channel info into driver's priv.
+ * iwl_set_ht40_chan_info - Copy ht40 channel info into driver's priv.
  *
  * Does not set up a command, or touch hardware.
  */
-static int iwl_set_fat_chan_info(struct iwl_priv *priv,
+static int iwl_set_ht40_chan_info(struct iwl_priv *priv,
 			      enum ieee80211_band band, u16 channel,
 			      const struct iwl_eeprom_channel *eeprom_ch,
-			      u8 fat_extension_channel)
+			      u8 ht40_extension_channel)
 {
 	struct iwl_channel_info *ch_info;
 
@@ -501,7 +501,7 @@ static int iwl_set_fat_chan_info(struct iwl_priv *priv,
 	if (!is_channel_valid(ch_info))
 		return -1;
 
-	IWL_DEBUG_INFO(priv, "FAT Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):"
+	IWL_DEBUG_INFO(priv, "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):"
 			" Ad-Hoc %ssupported\n",
 			ch_info->channel,
 			is_channel_a_band(ch_info) ?
@@ -517,13 +517,13 @@ static int iwl_set_fat_chan_info(struct iwl_priv *priv,
 			 && !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ?
 			"" : "not ");
 
-	ch_info->fat_eeprom = *eeprom_ch;
-	ch_info->fat_max_power_avg = eeprom_ch->max_power_avg;
-	ch_info->fat_curr_txpow = eeprom_ch->max_power_avg;
-	ch_info->fat_min_power = 0;
-	ch_info->fat_scan_power = eeprom_ch->max_power_avg;
-	ch_info->fat_flags = eeprom_ch->flags;
-	ch_info->fat_extension_channel = fat_extension_channel;
+	ch_info->ht40_eeprom = *eeprom_ch;
+	ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg;
+	ch_info->ht40_curr_txpow = eeprom_ch->max_power_avg;
+	ch_info->ht40_min_power = 0;
+	ch_info->ht40_scan_power = eeprom_ch->max_power_avg;
+	ch_info->ht40_flags = eeprom_ch->flags;
+	ch_info->ht40_extension_channel = ht40_extension_channel;
 
 	return 0;
 }
@@ -589,9 +589,9 @@ int iwl_init_channel_map(struct iwl_priv *priv)
 			/* Copy the run-time flags so they are there even on
 			 * invalid channels */
 			ch_info->flags = eeprom_ch_info[ch].flags;
-			/* First write that fat is not enabled, and then enable
+			/* First write that ht40 is not enabled, and then enable
 			 * one by one */
-			ch_info->fat_extension_channel =
+			ch_info->ht40_extension_channel =
 				(IEEE80211_CHAN_NO_HT40PLUS |
 				 IEEE80211_CHAN_NO_HT40MINUS);
 
@@ -642,17 +642,17 @@ int iwl_init_channel_map(struct iwl_priv *priv)
 		}
 	}
 
-	/* Check if we do have FAT channels */
+	/* Check if we do have HT40 channels */
 	if (priv->cfg->ops->lib->eeprom_ops.regulatory_bands[5] ==
-	    EEPROM_REGULATORY_BAND_NO_FAT &&
+	    EEPROM_REGULATORY_BAND_NO_HT40 &&
 	    priv->cfg->ops->lib->eeprom_ops.regulatory_bands[6] ==
-	    EEPROM_REGULATORY_BAND_NO_FAT)
+	    EEPROM_REGULATORY_BAND_NO_HT40)
 		return 0;
 
-	/* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */
+	/* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */
 	for (band = 6; band <= 7; band++) {
 		enum ieee80211_band ieeeband;
-		u8 fat_extension_chan;
+		u8 ht40_extension_chan;
 
 		iwl_init_band_reference(priv, band, &eeprom_ch_count,
 					&eeprom_ch_info, &eeprom_ch_index);
@@ -669,19 +669,19 @@ int iwl_init_channel_map(struct iwl_priv *priv)
 				 (eeprom_ch_index[ch] == 6) ||
 				 (eeprom_ch_index[ch] == 7)))
 				/* both are allowed: above and below */
-				fat_extension_chan = 0;
+				ht40_extension_chan = 0;
 			else
-				fat_extension_chan =
+				ht40_extension_chan =
 					IEEE80211_CHAN_NO_HT40MINUS;
 
 			/* Set up driver's info for lower half */
-			iwl_set_fat_chan_info(priv, ieeeband,
+			iwl_set_ht40_chan_info(priv, ieeeband,
 						eeprom_ch_index[ch],
 						&(eeprom_ch_info[ch]),
-						fat_extension_chan);
+						ht40_extension_chan);
 
 			/* Set up driver's info for upper half */
-			iwl_set_fat_chan_info(priv, ieeeband,
+			iwl_set_ht40_chan_info(priv, ieeeband,
 						(eeprom_ch_index[ch] + 4),
 						&(eeprom_ch_info[ch]),
 						IEEE80211_CHAN_NO_HT40PLUS);
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index 195b4ef..05d4fc4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -88,10 +88,10 @@ struct iwl_priv;
  * requirement for establishing a new network for legal operation on channels
  * requiring RADAR detection or restricting ACTIVE scanning.
  *
- * NOTE:  "WIDE" flag does not indicate anything about "FAT" 40 MHz channels.
- *        It only indicates that 20 MHz channel use is supported; FAT channel
+ * NOTE:  "WIDE" flag does not indicate anything about "HT40" 40 MHz channels.
+ *        It only indicates that 20 MHz channel use is supported; HT40 channel
  *        usage is indicated by a separate set of regulatory flags for each
- *        FAT channel pair.
+ *        HT40 channel pair.
  *
  * NOTE:  Using a channel inappropriately will result in a uCode error!
  */
@@ -112,7 +112,7 @@ enum {
 #define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE                (1 << 1)
 
 /* *regulatory* channel data format in eeprom, one for each channel.
- * There are separate entries for FAT (40 MHz) vs. normal (20 MHz) channels. */
+ * There are separate entries for HT40 (40 MHz) vs. normal (20 MHz) channels. */
 struct iwl_eeprom_channel {
 	u8 flags;		/* EEPROM_CHANNEL_* flags copied from EEPROM */
 	s8 max_power_avg;	/* max power (dBm) on this chnl, limit 31 */
@@ -170,9 +170,9 @@ struct iwl_eeprom_channel {
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 22 bytes */
 #define EEPROM_5000_REG_BAND_5_CHANNELS       ((0x74)\
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 12 bytes */
-#define EEPROM_5000_REG_BAND_24_FAT_CHANNELS  ((0x82)\
+#define EEPROM_5000_REG_BAND_24_HT40_CHANNELS  ((0x82)\
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 14  bytes */
-#define EEPROM_5000_REG_BAND_52_FAT_CHANNELS  ((0x92)\
+#define EEPROM_5000_REG_BAND_52_HT40_CHANNELS  ((0x92)\
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 22  bytes */
 
 /* 5050 Specific */
@@ -313,7 +313,7 @@ struct iwl_eeprom_calib_info {
  * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
  * txpower (MSB).
  *
- * Entries immediately below are for 20 MHz channel width.  FAT (40 MHz)
+ * Entries immediately below are for 20 MHz channel width.  HT40 (40 MHz)
  * channels (only for 4965, not supported by 3945) appear later in the EEPROM.
  *
  * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
@@ -352,29 +352,29 @@ struct iwl_eeprom_calib_info {
 #define EEPROM_REGULATORY_BAND_5_CHANNELS   (2*0x99)	/* 12 bytes */
 
 /*
- * 2.4 GHz FAT channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11)
+ * 2.4 GHz HT40 channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11)
  *
  * The channel listed is the center of the lower 20 MHz half of the channel.
  * The overall center frequency is actually 2 channels (10 MHz) above that,
- * and the upper half of each FAT channel is centered 4 channels (20 MHz) away
- * from the lower half; e.g. the upper half of FAT channel 1 is channel 5,
- * and the overall FAT channel width centers on channel 3.
+ * and the upper half of each HT40 channel is centered 4 channels (20 MHz) away
+ * from the lower half; e.g. the upper half of HT40 channel 1 is channel 5,
+ * and the overall HT40 channel width centers on channel 3.
  *
  * NOTE:  The RXON command uses 20 MHz channel numbers to specify the
  *        control channel to which to tune.  RXON also specifies whether the
- *        control channel is the upper or lower half of a FAT channel.
+ *        control channel is the upper or lower half of a HT40 channel.
  *
- * NOTE:  4965 does not support FAT channels on 2.4 GHz.
+ * NOTE:  4965 does not support HT40 channels on 2.4 GHz.
  */
-#define EEPROM_4965_REGULATORY_BAND_24_FAT_CHANNELS (2*0xA0)	/* 14 bytes */
+#define EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS (2*0xA0)	/* 14 bytes */
 
 /*
- * 5.2 GHz FAT channels 36 (40), 44 (48), 52 (56), 60 (64),
+ * 5.2 GHz HT40 channels 36 (40), 44 (48), 52 (56), 60 (64),
  * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161)
  */
-#define EEPROM_4965_REGULATORY_BAND_52_FAT_CHANNELS (2*0xA8)	/* 22 bytes */
+#define EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS (2*0xA8)	/* 22 bytes */
 
-#define EEPROM_REGULATORY_BAND_NO_FAT			(0)
+#define EEPROM_REGULATORY_BAND_NO_HT40			(0)
 
 struct iwl_eeprom_ops {
 	const u32 regulatory_bands[7];
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 00937b3..594b5c2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -583,7 +583,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
 				/* disable HT */
 				rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
 					RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
-					RXON_FLG_FAT_PROT_MSK |
+					RXON_FLG_HT40_PROT_MSK |
 					RXON_FLG_HT_PROT_MSK);
 			else {
 				/* check HT capability and set
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 98f0142..9e63f9d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -544,8 +544,8 @@ void iwl_rx_statistics(struct iwl_priv *priv,
 	change = ((priv->statistics.general.temperature !=
 		   pkt->u.stats.general.temperature) ||
 		  ((priv->statistics.flag &
-		    STATISTICS_REPLY_FLG_FAT_MODE_MSK) !=
-		   (pkt->u.stats.flag & STATISTICS_REPLY_FLG_FAT_MODE_MSK)));
+		    STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
+		   (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
 
 	memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index def1254..c6633fe 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -214,10 +214,10 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
 	sta_flags |= cpu_to_le32(
 	      (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
 
-	if (iwl_is_fat_tx_allowed(priv, sta_ht_inf))
-		sta_flags |= STA_FLG_FAT_EN_MSK;
+	if (iwl_is_ht40_tx_allowed(priv, sta_ht_inf))
+		sta_flags |= STA_FLG_HT40_EN_MSK;
 	else
-		sta_flags &= ~STA_FLG_FAT_EN_MSK;
+		sta_flags &= ~STA_FLG_HT40_EN_MSK;
 
 	priv->stations[index].sta.station_flags = sta_flags;
  done:
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 03/16] iwlwifi: new debugging feature for dumping data traffic
  2009-08-07 22:41 [PATCH 0/16] iwlwifi driver updates 07/08/2009 Reinette Chatre
  2009-08-07 22:41 ` [PATCH 01/16] iwlwifi: re-introduce per device debugging Reinette Chatre
  2009-08-07 22:41 ` [PATCH 02/16] iwlwifi: name changed from "fat" to "ht40" Reinette Chatre
@ 2009-08-07 22:41 ` Reinette Chatre
  2009-08-07 22:41 ` [PATCH 04/16] iwlwifi: Traffic type and counter for debugFs Reinette Chatre
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

The traffic buffer will only beallocated and used if either bit 23
(IWL_DX_TX) or bit 24 (IWL_DL_RX) of "debug" is set;
example: "debug=0x800000" - log tx data traffic
         "debug=0x1000000" - log rx data traffic
         "debug=0x1800000" - log both tx and rx traffic

The traffic log will store the beginning portion (64 bytes)  of the
latest 256 of tx and rx packets in the round-robbin buffer for
debugging,
user can examine the log through debugfs file.

How to display the current logged tx/rx traffic and txfifo and rxfifo
read/write point:
"cat traffic_log" in /sys/kernel/debug/ieee80211/phy0/iwlagn/debug
directory

By echo "0" to traffic_log file will empty the traffic log buffer and
reset both tx and rx taffic log index to 0.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-3945.c     |    1 +
 drivers/net/wireless/iwlwifi/iwl-agn.c      |   11 +++-
 drivers/net/wireless/iwlwifi/iwl-core.c     |  100 ++++++++++++++++++++++++++
 drivers/net/wireless/iwlwifi/iwl-core.h     |   28 +++++++
 drivers/net/wireless/iwlwifi/iwl-debug.h    |    4 +
 drivers/net/wireless/iwlwifi/iwl-debugfs.c  |  102 +++++++++++++++++++++++++++
 drivers/net/wireless/iwlwifi/iwl-dev.h      |    6 ++
 drivers/net/wireless/iwlwifi/iwl-rx.c       |    1 +
 drivers/net/wireless/iwlwifi/iwl-tx.c       |    1 +
 drivers/net/wireless/iwlwifi/iwl3945-base.c |   13 +++-
 10 files changed, 262 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 9e33507..bfd509f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -679,6 +679,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
 
 	/* Set "1" to report good data frames in groups of 100 */
 	iwl3945_dbg_report_frame(priv, pkt, header, 1);
+	iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header);
 
 	if (network_packet) {
 		priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 24c1ae6..c9a1aac 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2476,9 +2476,12 @@ static ssize_t store_debug_level(struct device *d,
 	ret = strict_strtoul(buf, 0, &val);
 	if (ret)
 		IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
-	else
+	else {
 		priv->debug_level = val;
-
+		if (iwl_alloc_traffic_mem(priv))
+			IWL_ERR(priv,
+				"Not enough memory to generate traffic log\n");
+	}
 	return strnlen(buf, count);
 }
 
@@ -2819,6 +2822,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 #ifdef CONFIG_IWLWIFI_DEBUG
 	atomic_set(&priv->restrict_refcnt, 0);
 #endif
+	if (iwl_alloc_traffic_mem(priv))
+		IWL_ERR(priv, "Not enough memory to generate traffic log\n");
 
 	/**************************
 	 * 2. Initializing PCI bus
@@ -3003,6 +3008,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	pci_disable_device(pdev);
  out_ieee80211_free_hw:
 	ieee80211_free_hw(priv->hw);
+	iwl_free_traffic_mem(priv);
  out:
 	return err;
 }
@@ -3061,6 +3067,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
 	 * until now... */
 	destroy_workqueue(priv->workqueue);
 	priv->workqueue = NULL;
+	iwl_free_traffic_mem(priv);
 
 	free_irq(priv->pci_dev->irq, priv);
 	pci_disable_msi(priv->pci_dev);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 5315d34..1ae2ce3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -2953,6 +2953,106 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
 }
 EXPORT_SYMBOL(iwl_mac_reset_tsf);
 
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+
+#define IWL_TRAFFIC_DUMP_SIZE	(IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES)
+
+void iwl_reset_traffic_log(struct iwl_priv *priv)
+{
+	priv->tx_traffic_idx = 0;
+	priv->rx_traffic_idx = 0;
+	if (priv->tx_traffic)
+		memset(priv->tx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE);
+	if (priv->rx_traffic)
+		memset(priv->rx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE);
+}
+
+int iwl_alloc_traffic_mem(struct iwl_priv *priv)
+{
+	u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE;
+
+	if (iwl_debug_level & IWL_DL_TX) {
+		if (!priv->tx_traffic) {
+			priv->tx_traffic =
+				kzalloc(traffic_size, GFP_KERNEL);
+			if (!priv->tx_traffic)
+				return -ENOMEM;
+		}
+	}
+	if (iwl_debug_level & IWL_DL_RX) {
+		if (!priv->rx_traffic) {
+			priv->rx_traffic =
+				kzalloc(traffic_size, GFP_KERNEL);
+			if (!priv->rx_traffic)
+				return -ENOMEM;
+		}
+	}
+	iwl_reset_traffic_log(priv);
+	return 0;
+}
+EXPORT_SYMBOL(iwl_alloc_traffic_mem);
+
+void iwl_free_traffic_mem(struct iwl_priv *priv)
+{
+	kfree(priv->tx_traffic);
+	priv->tx_traffic = NULL;
+
+	kfree(priv->rx_traffic);
+	priv->rx_traffic = NULL;
+}
+EXPORT_SYMBOL(iwl_free_traffic_mem);
+
+void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
+		      u16 length, struct ieee80211_hdr *header)
+{
+	__le16 fc;
+	u16 len;
+
+	if (likely(!(iwl_debug_level & IWL_DL_TX)))
+		return;
+
+	if (!priv->tx_traffic)
+		return;
+
+	fc = header->frame_control;
+	if (ieee80211_is_data(fc)) {
+		len = (length > IWL_TRAFFIC_ENTRY_SIZE)
+		       ? IWL_TRAFFIC_ENTRY_SIZE : length;
+		memcpy((priv->tx_traffic +
+		       (priv->tx_traffic_idx * IWL_TRAFFIC_ENTRY_SIZE)),
+		       header, len);
+		priv->tx_traffic_idx =
+			(priv->tx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
+	}
+}
+EXPORT_SYMBOL(iwl_dbg_log_tx_data_frame);
+
+void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
+		      u16 length, struct ieee80211_hdr *header)
+{
+	__le16 fc;
+	u16 len;
+
+	if (likely(!(iwl_debug_level & IWL_DL_RX)))
+		return;
+
+	if (!priv->rx_traffic)
+		return;
+
+	fc = header->frame_control;
+	if (ieee80211_is_data(fc)) {
+		len = (length > IWL_TRAFFIC_ENTRY_SIZE)
+		       ? IWL_TRAFFIC_ENTRY_SIZE : length;
+		memcpy((priv->rx_traffic +
+		       (priv->rx_traffic_idx * IWL_TRAFFIC_ENTRY_SIZE)),
+		       header, len);
+		priv->rx_traffic_idx =
+			(priv->rx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
+	}
+}
+EXPORT_SYMBOL(iwl_dbg_log_rx_data_frame);
+#endif
+
 #ifdef CONFIG_PM
 
 int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index dd66148..40a9167 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -300,7 +300,35 @@ void iwl_config_ap(struct iwl_priv *priv);
 int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
 			 struct ieee80211_tx_queue_stats *stats);
 void iwl_mac_reset_tsf(struct ieee80211_hw *hw);
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+int iwl_alloc_traffic_mem(struct iwl_priv *priv);
+void iwl_free_traffic_mem(struct iwl_priv *priv);
+void iwl_reset_traffic_log(struct iwl_priv *priv);
+void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
+				u16 length, struct ieee80211_hdr *header);
+void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
+				u16 length, struct ieee80211_hdr *header);
 
+#else
+static inline int iwl_alloc_traffic_mem(struct iwl_priv *priv)
+{
+	return 0;
+}
+static inline void iwl_free_traffic_mem(struct iwl_priv *priv)
+{
+}
+static inline void iwl_reset_traffic_log(struct iwl_priv *priv)
+{
+}
+static inline void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
+		      u16 length, struct ieee80211_hdr *header)
+{
+}
+static inline void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
+		      u16 length, struct ieee80211_hdr *header)
+{
+}
+#endif
 /*****************************************************
  * RX handlers.
  * **************************************************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 09af046..335ff5c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -72,6 +72,7 @@ struct iwl_debugfs {
 	const char *name;
 	struct dentry *dir_drv;
 	struct dentry *dir_data;
+	struct dentry *dir_debug;
 	struct dentry *dir_rf;
 	struct dir_data_files {
 		struct dentry *file_sram;
@@ -95,6 +96,9 @@ struct iwl_debugfs {
 		struct dentry *file_disable_chain_noise;
 		struct dentry *file_disable_tx_power;
 	} dbgfs_rf_files;
+	struct dir_debug_files {
+		struct dentry *file_traffic_log;
+	} dbgfs_debug_files;
 	u32 sram_offset;
 	u32 sram_len;
 };
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 6748a3f..031538c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -712,6 +712,104 @@ DEBUGFS_READ_FILE_OPS(led);
 DEBUGFS_READ_FILE_OPS(thermal_throttling);
 DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
 
+static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
+					 char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0, ofs = 0;
+	int cnt = 0, entry;
+	struct iwl_tx_queue *txq;
+	struct iwl_queue *q;
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	char *buf;
+	int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
+		(IWL_MAX_NUM_QUEUES * 32 * 8) + 400;
+	const u8 *ptr;
+	ssize_t ret;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate buffer\n");
+		return -ENOMEM;
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
+	for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
+		txq = &priv->txq[cnt];
+		q = &txq->q;
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"q[%d]: read_ptr: %u, write_ptr: %u\n",
+				cnt, q->read_ptr, q->write_ptr);
+	}
+	if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) {
+		ptr = priv->tx_traffic;
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"Tx Traffic idx: %u\n",	priv->tx_traffic_idx);
+		for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
+			for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
+			     entry++,  ofs += 16) {
+				pos += scnprintf(buf + pos, bufsz - pos,
+						"0x%.4x ", ofs);
+				hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
+						   buf + pos, bufsz - pos, 0);
+				pos += strlen(buf);
+				if (bufsz - pos > 0)
+					buf[pos++] = '\n';
+			}
+		}
+	}
+
+	pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"read: %u, write: %u\n",
+			 rxq->read, rxq->write);
+
+	if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) {
+		ptr = priv->rx_traffic;
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"Rx Traffic idx: %u\n",	priv->rx_traffic_idx);
+		for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
+			for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
+			     entry++,  ofs += 16) {
+				pos += scnprintf(buf + pos, bufsz - pos,
+						"0x%.4x ", ofs);
+				hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
+						   buf + pos, bufsz - pos, 0);
+				pos += strlen(buf);
+				if (bufsz - pos > 0)
+					buf[pos++] = '\n';
+			}
+		}
+	}
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_dbgfs_traffic_log_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 traffic_log;
+
+	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", &traffic_log) != 1)
+		return -EFAULT;
+	if (traffic_log == 0)
+		iwl_reset_traffic_log(priv);
+
+	return count;
+}
+
+DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
+
 /*
  * Create the debugfs files and directories
  *
@@ -738,6 +836,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
 
 	DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
 	DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv);
+	DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv);
 	DEBUGFS_ADD_FILE(nvm, data);
 	DEBUGFS_ADD_FILE(sram, data);
 	DEBUGFS_ADD_FILE(log_event, data);
@@ -753,6 +852,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
 #endif
 	DEBUGFS_ADD_FILE(thermal_throttling, data);
 	DEBUGFS_ADD_FILE(disable_ht40, data);
+	DEBUGFS_ADD_FILE(traffic_log, debug);
 	DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
 	DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
 			 &priv->disable_chain_noise_cal);
@@ -794,6 +894,8 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40);
 	DEBUGFS_REMOVE(priv->dbgfs->dir_data);
+	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log);
+	DEBUGFS_REMOVE(priv->dbgfs->dir_debug);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
 	if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 624656a..899b75f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -877,6 +877,8 @@ struct iwl_chain_noise_data {
 #define	EEPROM_SEM_TIMEOUT 10		/* milliseconds */
 #define EEPROM_SEM_RETRY_LIMIT 1000	/* number of attempts (not time) */
 
+#define IWL_TRAFFIC_ENTRIES	(256)
+#define IWL_TRAFFIC_ENTRY_SIZE  (64)
 
 enum {
 	MEASUREMENT_READY = (1 << 0),
@@ -1182,6 +1184,10 @@ struct iwl_priv {
 	bool disable_ht40;
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 	/* debugfs */
+	u16 tx_traffic_idx;
+	u16 rx_traffic_idx;
+	u8 *tx_traffic;
+	u8 *rx_traffic;
 	struct iwl_debugfs *dbgfs;
 #endif /* CONFIG_IWLWIFI_DEBUGFS */
 #endif /* CONFIG_IWLWIFI_DEBUG */
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 9e63f9d..5586003 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -1063,6 +1063,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
 	if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX))
 		iwl_dbg_report_frame(priv, rx_start, len, header, 1);
 #endif
+	iwl_dbg_log_rx_data_frame(priv, len, header);
 	IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n",
 		rx_status.signal, rx_status.noise, rx_status.qual,
 		(unsigned long long)rx_status.mactime);
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 0cac06c..c85e54c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -808,6 +808,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
 	/* TODO need this for burst mode later on */
 	iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id);
+	iwl_dbg_log_tx_data_frame(priv, len, hdr);
 
 	/* set is_hcca to 0; it probably will never be implemented */
 	iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, sta_id, 0);
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 0babce2..4f5a3d0 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -598,7 +598,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 	len = (u16)skb->len;
 	tx->len = cpu_to_le16(len);
 
-
+	iwl_dbg_log_tx_data_frame(priv, len, hdr);
 	tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
 	tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
 
@@ -3332,9 +3332,12 @@ static ssize_t store_debug_level(struct device *d,
 	ret = strict_strtoul(buf, 0, &val);
 	if (ret)
 		IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf);
-	else
+	else {
 		priv->debug_level = val;
-
+		if (iwl_alloc_traffic_mem(priv))
+			IWL_ERR(priv,
+				"Not enough memory to generate traffic log\n");
+	}
 	return strnlen(buf, count);
 }
 
@@ -3976,6 +3979,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 #ifdef CONFIG_IWLWIFI_DEBUG
 	atomic_set(&priv->restrict_refcnt, 0);
 #endif
+	if (iwl_alloc_traffic_mem(priv))
+		IWL_ERR(priv, "Not enough memory to generate traffic log\n");
 
 	/***************************
 	 * 2. Initializing PCI bus
@@ -4138,6 +4143,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 	pci_disable_device(pdev);
  out_ieee80211_free_hw:
 	ieee80211_free_hw(priv->hw);
+	iwl_free_traffic_mem(priv);
  out:
 	return err;
 }
@@ -4193,6 +4199,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
 	 * until now... */
 	destroy_workqueue(priv->workqueue);
 	priv->workqueue = NULL;
+	iwl_free_traffic_mem(priv);
 
 	free_irq(pdev->irq, priv);
 	pci_disable_msi(pdev);
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 04/16] iwlwifi: Traffic type and counter for debugFs
  2009-08-07 22:41 [PATCH 0/16] iwlwifi driver updates 07/08/2009 Reinette Chatre
                   ` (2 preceding siblings ...)
  2009-08-07 22:41 ` [PATCH 03/16] iwlwifi: new debugging feature for dumping data traffic Reinette Chatre
@ 2009-08-07 22:41 ` Reinette Chatre
  2009-08-07 22:41 ` [PATCH 05/16] iwlwifi: tx/rx queue pointer information Reinette Chatre
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

Break down the traffic type and counter for both Tx and Rx.
Enhance the tx_statistics and rx_statistics debugfs function and move
to /sys/kernel/debug/ieee80211/phy0/iwlagn/debug directory to help
better debugging both driver and uCode related problems.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-3945.c     |    2 +
 drivers/net/wireless/iwlwifi/iwl-core.c     |  158 +++++++++++++++++++++++++++
 drivers/net/wireless/iwlwifi/iwl-core.h     |    9 ++-
 drivers/net/wireless/iwlwifi/iwl-debug.h    |    4 +-
 drivers/net/wireless/iwlwifi/iwl-debugfs.c  |  129 ++++++++++++++++++----
 drivers/net/wireless/iwlwifi/iwl-dev.h      |   48 ++++++++-
 drivers/net/wireless/iwlwifi/iwl-hcmd.c     |    2 -
 drivers/net/wireless/iwlwifi/iwl-led.c      |    3 +-
 drivers/net/wireless/iwlwifi/iwl-rx.c       |   10 +--
 drivers/net/wireless/iwlwifi/iwl-tx.c       |   11 +--
 drivers/net/wireless/iwlwifi/iwl3945-base.c |    1 +
 11 files changed, 324 insertions(+), 53 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index bfd509f..ae7f163 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -577,6 +577,8 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
 	if (ieee80211_is_data(hdr->frame_control))
 		priv->rxtxpackets += len;
 #endif
+	iwl_update_stats(priv, false, hdr->frame_control, len);
+
 	memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));
 	ieee80211_rx_irqsafe(priv->hw, rxb->skb);
 	rxb->skb = NULL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 1ae2ce3..202bc39 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -3051,6 +3051,164 @@ void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
 	}
 }
 EXPORT_SYMBOL(iwl_dbg_log_rx_data_frame);
+
+const char *get_mgmt_string(int cmd)
+{
+	switch (cmd) {
+		IWL_CMD(MANAGEMENT_ASSOC_REQ);
+		IWL_CMD(MANAGEMENT_ASSOC_RESP);
+		IWL_CMD(MANAGEMENT_REASSOC_REQ);
+		IWL_CMD(MANAGEMENT_REASSOC_RESP);
+		IWL_CMD(MANAGEMENT_PROBE_REQ);
+		IWL_CMD(MANAGEMENT_PROBE_RESP);
+		IWL_CMD(MANAGEMENT_BEACON);
+		IWL_CMD(MANAGEMENT_ATIM);
+		IWL_CMD(MANAGEMENT_DISASSOC);
+		IWL_CMD(MANAGEMENT_AUTH);
+		IWL_CMD(MANAGEMENT_DEAUTH);
+		IWL_CMD(MANAGEMENT_ACTION);
+	default:
+		return "UNKNOWN";
+
+	}
+}
+
+const char *get_ctrl_string(int cmd)
+{
+	switch (cmd) {
+		IWL_CMD(CONTROL_BACK_REQ);
+		IWL_CMD(CONTROL_BACK);
+		IWL_CMD(CONTROL_PSPOLL);
+		IWL_CMD(CONTROL_RTS);
+		IWL_CMD(CONTROL_CTS);
+		IWL_CMD(CONTROL_ACK);
+		IWL_CMD(CONTROL_CFEND);
+		IWL_CMD(CONTROL_CFENDACK);
+	default:
+		return "UNKNOWN";
+
+	}
+}
+
+void iwl_clear_tx_stats(struct iwl_priv *priv)
+{
+	memset(&priv->tx_stats, 0, sizeof(struct traffic_stats));
+
+}
+
+void iwl_clear_rx_stats(struct iwl_priv *priv)
+{
+	memset(&priv->rx_stats, 0, sizeof(struct traffic_stats));
+}
+
+/*
+ * if CONFIG_IWLWIFI_DEBUGFS defined, iwl_update_stats function will
+ * record all the MGMT, CTRL and DATA pkt for both TX and Rx pass.
+ * Use debugFs to display the rx/rx_statistics
+ * if CONFIG_IWLWIFI_DEBUGFS not being defined, then no MGMT and CTRL
+ * information will be recorded, but DATA pkt still will be recorded
+ * for the reason of iwl_led.c need to control the led blinking based on
+ * number of tx and rx data.
+ *
+ */
+void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
+{
+	struct traffic_stats	*stats;
+
+	if (is_tx)
+		stats = &priv->tx_stats;
+	else
+		stats = &priv->rx_stats;
+
+	if (ieee80211_is_mgmt(fc)) {
+		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
+		case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
+			stats->mgmt[MANAGEMENT_ASSOC_REQ]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
+			stats->mgmt[MANAGEMENT_ASSOC_RESP]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
+			stats->mgmt[MANAGEMENT_REASSOC_REQ]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
+			stats->mgmt[MANAGEMENT_REASSOC_RESP]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
+			stats->mgmt[MANAGEMENT_PROBE_REQ]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
+			stats->mgmt[MANAGEMENT_PROBE_RESP]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_BEACON):
+			stats->mgmt[MANAGEMENT_BEACON]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_ATIM):
+			stats->mgmt[MANAGEMENT_ATIM]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
+			stats->mgmt[MANAGEMENT_DISASSOC]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_AUTH):
+			stats->mgmt[MANAGEMENT_AUTH]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
+			stats->mgmt[MANAGEMENT_DEAUTH]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_ACTION):
+			stats->mgmt[MANAGEMENT_ACTION]++;
+			break;
+		}
+	} else if (ieee80211_is_ctl(fc)) {
+		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
+		case cpu_to_le16(IEEE80211_STYPE_BACK_REQ):
+			stats->ctrl[CONTROL_BACK_REQ]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_BACK):
+			stats->ctrl[CONTROL_BACK]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_PSPOLL):
+			stats->ctrl[CONTROL_PSPOLL]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_RTS):
+			stats->ctrl[CONTROL_RTS]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_CTS):
+			stats->ctrl[CONTROL_CTS]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_ACK):
+			stats->ctrl[CONTROL_ACK]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_CFEND):
+			stats->ctrl[CONTROL_CFEND]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_CFENDACK):
+			stats->ctrl[CONTROL_CFENDACK]++;
+			break;
+		}
+	} else {
+		/* data */
+		stats->data_cnt++;
+		stats->data_bytes += len;
+	}
+}
+EXPORT_SYMBOL(iwl_update_stats);
+
+#else
+void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
+{
+	struct traffic_stats	*stats;
+
+	if (is_tx)
+		stats = &priv->tx_stats;
+	else
+		stats = &priv->rx_stats;
+
+	if (ieee80211_is_data(fc)) {
+		/* data */
+		stats->data_bytes += len;
+	}
+}
 #endif
 
 #ifdef CONFIG_PM
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 40a9167..fc096b9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -83,6 +83,8 @@ struct iwl_cmd;
 #define IWL_SKU_A       0x2
 #define IWL_SKU_N       0x8
 
+#define IWL_CMD(x) case x: return #x
+
 struct iwl_hcmd_ops {
 	int (*rxon_assoc)(struct iwl_priv *priv);
 	int (*commit_rxon)(struct iwl_priv *priv);
@@ -308,7 +310,10 @@ void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
 				u16 length, struct ieee80211_hdr *header);
 void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
 				u16 length, struct ieee80211_hdr *header);
-
+const char *get_mgmt_string(int cmd);
+const char *get_ctrl_string(int cmd);
+void iwl_clear_tx_stats(struct iwl_priv *priv);
+void iwl_clear_rx_stats(struct iwl_priv *priv);
 #else
 static inline int iwl_alloc_traffic_mem(struct iwl_priv *priv)
 {
@@ -329,6 +334,8 @@ static inline void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
 {
 }
 #endif
+void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc,
+		      u16 len);
 /*****************************************************
  * RX handlers.
  * **************************************************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 335ff5c..4ac06ad 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -78,8 +78,6 @@ struct iwl_debugfs {
 		struct dentry *file_sram;
 		struct dentry *file_nvm;
 		struct dentry *file_stations;
-		struct dentry *file_rx_statistics;
-		struct dentry *file_tx_statistics;
 		struct dentry *file_log_event;
 		struct dentry *file_channels;
 		struct dentry *file_status;
@@ -97,6 +95,8 @@ struct iwl_debugfs {
 		struct dentry *file_disable_tx_power;
 	} dbgfs_rf_files;
 	struct dir_debug_files {
+		struct dentry *file_rx_statistics;
+		struct dentry *file_tx_statistics;
 		struct dentry *file_traffic_log;
 	} dbgfs_debug_files;
 	u32 sram_offset;
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 031538c..a0e5063 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -126,18 +126,58 @@ static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
 						size_t count, loff_t *ppos) {
 
 	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
-	char buf[256];
+	char *buf;
 	int pos = 0;
-	const size_t bufsz = sizeof(buf);
 
-	pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n",
-						priv->tx_stats[0].cnt);
-	pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n",
-						priv->tx_stats[1].cnt);
-	pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n",
-						priv->tx_stats[2].cnt);
+	int cnt;
+	ssize_t ret;
+	const size_t bufsz = 100 + sizeof(char) * 24 * (MANAGEMENT_MAX + CONTROL_MAX);
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
+	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos,
+				 "\t%s\t\t: %u\n",
+				 get_mgmt_string(cnt),
+				 priv->tx_stats.mgmt[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
+	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos,
+				 "\t%s\t\t: %u\n",
+				 get_ctrl_string(cnt),
+				 priv->tx_stats.ctrl[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
+			 priv->tx_stats.data_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
+			 priv->tx_stats.data_bytes);
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_dbgfs_tx_statistics_write(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	u32 clear_flag;
+	char buf[8];
+	int buf_size;
 
-	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	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, "%x", &clear_flag) != 1)
+		return -EFAULT;
+	if (clear_flag == 1)
+		iwl_clear_tx_stats(priv);
+
+	return count;
 }
 
 static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
@@ -145,18 +185,59 @@ static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
 						size_t count, loff_t *ppos) {
 
 	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
-	char buf[256];
+	char *buf;
 	int pos = 0;
-	const size_t bufsz = sizeof(buf);
+	int cnt;
+	ssize_t ret;
+	const size_t bufsz = 100 +
+		sizeof(char) * 24 * (MANAGEMENT_MAX + CONTROL_MAX);
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
 
-	pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n",
-						priv->rx_stats[0].cnt);
-	pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n",
-						priv->rx_stats[1].cnt);
-	pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n",
-						priv->rx_stats[2].cnt);
+	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
+	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos,
+				 "\t%s\t\t: %u\n",
+				 get_mgmt_string(cnt),
+				 priv->rx_stats.mgmt[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
+	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos,
+				 "\t%s\t\t: %u\n",
+				 get_ctrl_string(cnt),
+				 priv->rx_stats.ctrl[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
+			 priv->rx_stats.data_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
+			 priv->rx_stats.data_bytes);
 
-	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_dbgfs_rx_statistics_write(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	u32 clear_flag;
+	char buf[8];
+	int buf_size;
+
+	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, "%x", &clear_flag) != 1)
+		return -EFAULT;
+	if (clear_flag == 1)
+		iwl_clear_rx_stats(priv);
+	return count;
 }
 
 #define BYTE1_MASK 0x000000ff;
@@ -700,8 +781,6 @@ DEBUGFS_READ_WRITE_FILE_OPS(sram);
 DEBUGFS_WRITE_FILE_OPS(log_event);
 DEBUGFS_READ_FILE_OPS(nvm);
 DEBUGFS_READ_FILE_OPS(stations);
-DEBUGFS_READ_FILE_OPS(rx_statistics);
-DEBUGFS_READ_FILE_OPS(tx_statistics);
 DEBUGFS_READ_FILE_OPS(channels);
 DEBUGFS_READ_FILE_OPS(status);
 DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
@@ -808,6 +887,8 @@ static ssize_t iwl_dbgfs_traffic_log_write(struct file *file,
 	return count;
 }
 
+DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics);
+DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics);
 DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
 
 /*
@@ -841,8 +922,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
 	DEBUGFS_ADD_FILE(sram, data);
 	DEBUGFS_ADD_FILE(log_event, data);
 	DEBUGFS_ADD_FILE(stations, data);
-	DEBUGFS_ADD_FILE(rx_statistics, data);
-	DEBUGFS_ADD_FILE(tx_statistics, data);
 	DEBUGFS_ADD_FILE(channels, data);
 	DEBUGFS_ADD_FILE(status, data);
 	DEBUGFS_ADD_FILE(interrupt, data);
@@ -852,6 +931,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
 #endif
 	DEBUGFS_ADD_FILE(thermal_throttling, data);
 	DEBUGFS_ADD_FILE(disable_ht40, data);
+	DEBUGFS_ADD_FILE(rx_statistics, debug);
+	DEBUGFS_ADD_FILE(tx_statistics, debug);
 	DEBUGFS_ADD_FILE(traffic_log, debug);
 	DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
 	DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
@@ -879,8 +960,6 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
 		return;
 
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm);
-	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics);
-	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
@@ -894,6 +973,8 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40);
 	DEBUGFS_REMOVE(priv->dbgfs->dir_data);
+	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_statistics);
+	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_statistics);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log);
 	DEBUGFS_REMOVE(priv->dbgfs->dir_debug);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 899b75f..dcf9d57 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -919,6 +919,48 @@ struct isr_statistics {
 	u32 unhandled;
 };
 
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+/* management statistics */
+enum iwl_mgmt_stats {
+	MANAGEMENT_ASSOC_REQ = 0,
+	MANAGEMENT_ASSOC_RESP,
+	MANAGEMENT_REASSOC_REQ,
+	MANAGEMENT_REASSOC_RESP,
+	MANAGEMENT_PROBE_REQ,
+	MANAGEMENT_PROBE_RESP,
+	MANAGEMENT_BEACON,
+	MANAGEMENT_ATIM,
+	MANAGEMENT_DISASSOC,
+	MANAGEMENT_AUTH,
+	MANAGEMENT_DEAUTH,
+	MANAGEMENT_ACTION,
+	MANAGEMENT_MAX,
+};
+/* control statistics */
+enum iwl_ctrl_stats {
+	CONTROL_BACK_REQ =  0,
+	CONTROL_BACK,
+	CONTROL_PSPOLL,
+	CONTROL_RTS,
+	CONTROL_CTS,
+	CONTROL_ACK,
+	CONTROL_CFEND,
+	CONTROL_CFENDACK,
+	CONTROL_MAX,
+};
+
+struct traffic_stats {
+	u32 mgmt[MANAGEMENT_MAX];
+	u32 ctrl[CONTROL_MAX];
+	u32 data_cnt;
+	u64 data_bytes;
+};
+#else
+struct traffic_stats {
+	u64 data_bytes;
+};
+#endif
+
 #define IWL_MAX_NUM_QUEUES	20 /* FIXME: do dynamic allocation */
 
 struct iwl_priv {
@@ -1064,10 +1106,8 @@ struct iwl_priv {
 	int last_rx_noise;	/* From beacon statistics */
 
 	/* counts mgmt, ctl, and data packets */
-	struct traffic_stats {
-		u32 cnt;
-		u64 bytes;
-	} tx_stats[3], rx_stats[3];
+	struct traffic_stats tx_stats;
+	struct traffic_stats rx_stats;
 
 	/* counts interrupts */
 	struct isr_statistics isr_stats;
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index b82ad15..532c8d6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -36,8 +36,6 @@
 #include "iwl-core.h"
 
 
-#define IWL_CMD(x) case x: return #x
-
 const char *get_cmd_string(u8 cmd)
 {
 	switch (cmd) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index 3d61cb4..f420c99 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -272,7 +272,8 @@ static int iwl_get_blink_rate(struct iwl_priv *priv)
 	/* count both tx and rx traffic to be able to
 	 * handle traffic in either direction
 	 */
-	u64 current_tpt = priv->tx_stats[2].bytes + priv->rx_stats[2].bytes;
+	u64 current_tpt = priv->tx_stats.data_bytes +
+			  priv->rx_stats.data_bytes;
 	s64 tpt = current_tpt - priv->led_tpt;
 
 	if (tpt < 0) /* wraparound */
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 5586003..43b2fce 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -745,14 +745,6 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv,
 }
 #endif
 
-static void iwl_update_rx_stats(struct iwl_priv *priv, u16 fc, u16 len)
-{
-	/* 0 - mgmt, 1 - cnt, 2 - data */
-	int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2;
-	priv->rx_stats[idx].cnt++;
-	priv->rx_stats[idx].bytes += len;
-}
-
 /*
  * returns non-zero if packet should be dropped
  */
@@ -930,7 +922,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
 	    iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
 		return;
 
-	iwl_update_rx_stats(priv, le16_to_cpu(hdr->frame_control), len);
+	iwl_update_stats(priv, false, hdr->frame_control, len);
 	memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));
 	ieee80211_rx_irqsafe(priv->hw, rxb->skb);
 	priv->alloc_rxb_skb--;
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index c85e54c..9b76bd4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -668,14 +668,6 @@ static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
 	}
 }
 
-static void iwl_update_tx_stats(struct iwl_priv *priv, u16 fc, u16 len)
-{
-	/* 0 - mgmt, 1 - cnt, 2 - data */
-	int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2;
-	priv->tx_stats[idx].cnt++;
-	priv->tx_stats[idx].bytes += len;
-}
-
 /*
  * start REPLY_TX command process
  */
@@ -813,8 +805,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 	/* set is_hcca to 0; it probably will never be implemented */
 	iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, sta_id, 0);
 
-	iwl_update_tx_stats(priv, le16_to_cpu(fc), len);
-
+	iwl_update_stats(priv, true, fc, len);
 	/*
 	 * Use the first empty entry in this queue's command buffer array
 	 * to contain the Tx command and MAC header concatenated together
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 4f5a3d0..e5fa672 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -599,6 +599,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 	tx->len = cpu_to_le16(len);
 
 	iwl_dbg_log_tx_data_frame(priv, len, hdr);
+	iwl_update_stats(priv, true, fc, len);
 	tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
 	tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
 
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 05/16] iwlwifi: tx/rx queue pointer information
  2009-08-07 22:41 [PATCH 0/16] iwlwifi driver updates 07/08/2009 Reinette Chatre
                   ` (3 preceding siblings ...)
  2009-08-07 22:41 ` [PATCH 04/16] iwlwifi: Traffic type and counter for debugFs Reinette Chatre
@ 2009-08-07 22:41 ` Reinette Chatre
  2009-08-07 22:41 ` [PATCH 06/16] iwlwifi: uCode statistics notification counter Reinette Chatre
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
  To: linville
  Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Johannes Berg,
	Reinette Chatre

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

Adding debugfs function to show current TxFifo/RxFifo read/write
pointer, plus the current tx queue status (wake/stop) for both real and
virtual queue.
This is part of debug feature set to help debugging driver/uCode.

use tx_queue and rx_queue in
/sys/kernel/debug/ieee80211/phy0/iwlagn/debug directory to show the
current read/write pointer for both TxFifo and RxFifo queue

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-debug.h   |    2 +
 drivers/net/wireless/iwlwifi/iwl-debugfs.c |   69 ++++++++++++++++++++++++++++
 2 files changed, 71 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 4ac06ad..cad5e27 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -98,6 +98,8 @@ struct iwl_debugfs {
 		struct dentry *file_rx_statistics;
 		struct dentry *file_tx_statistics;
 		struct dentry *file_traffic_log;
+		struct dentry *file_rx_queue;
+		struct dentry *file_tx_queue;
 	} dbgfs_debug_files;
 	u32 sram_offset;
 	u32 sram_len;
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index a0e5063..d4109cb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -887,9 +887,74 @@ static ssize_t iwl_dbgfs_traffic_log_write(struct file *file,
 	return count;
 }
 
+static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+	struct iwl_tx_queue *txq;
+	struct iwl_queue *q;
+	char *buf;
+	int pos = 0;
+	int cnt;
+	int ret;
+	const size_t bufsz = sizeof(char) * 60 * IWL_MAX_NUM_QUEUES;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
+		txq = &priv->txq[cnt];
+		q = &txq->q;
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"hwq %.2d: read=%u write=%u stop=%d"
+				" swq_id=%#.2x (ac %d/hwq %d)\n",
+				cnt, q->read_ptr, q->write_ptr,
+				!!test_bit(cnt, priv->queue_stopped),
+				txq->swq_id,
+				txq->swq_id & 0x80 ? txq->swq_id & 3 :
+				txq->swq_id,
+				txq->swq_id & 0x80 ? (txq->swq_id >> 2) &
+				0x1f : txq->swq_id);
+		if (cnt >= 4)
+			continue;
+		/* for the ACs, display the stop count too */
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"        stop-count: %d\n",
+				atomic_read(&priv->queue_stop_count[cnt]));
+	}
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	char buf[256];
+	int pos = 0;
+	const size_t bufsz = sizeof(buf);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
+						rxq->read);
+	pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
+						rxq->write);
+	pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
+						rxq->free_count);
+	pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
+			 le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF);
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
 DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics);
 DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics);
 DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
+DEBUGFS_READ_FILE_OPS(rx_queue);
+DEBUGFS_READ_FILE_OPS(tx_queue);
 
 /*
  * Create the debugfs files and directories
@@ -934,6 +999,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
 	DEBUGFS_ADD_FILE(rx_statistics, debug);
 	DEBUGFS_ADD_FILE(tx_statistics, debug);
 	DEBUGFS_ADD_FILE(traffic_log, debug);
+	DEBUGFS_ADD_FILE(rx_queue, debug);
+	DEBUGFS_ADD_FILE(tx_queue, debug);
 	DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
 	DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
 			 &priv->disable_chain_noise_cal);
@@ -976,6 +1043,8 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_statistics);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_statistics);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log);
+	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue);
+	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue);
 	DEBUGFS_REMOVE(priv->dbgfs->dir_debug);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 06/16] iwlwifi: uCode statistics notification counter
  2009-08-07 22:41 [PATCH 0/16] iwlwifi driver updates 07/08/2009 Reinette Chatre
                   ` (4 preceding siblings ...)
  2009-08-07 22:41 ` [PATCH 05/16] iwlwifi: tx/rx queue pointer information Reinette Chatre
@ 2009-08-07 22:41 ` Reinette Chatre
  2009-08-07 22:41 ` [PATCH 07/16] iwlwifi: Display sensitivity and chain noise information Reinette Chatre
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

Display statistics notification information
The information break down into
    uCode_tx_stats
    uCode_rx_stats
    uCode_general_stats
and can be found in /sys/kernel/debug/ieee80211/phy0/iwlagn/debug
directory

The statistic information display in debugFs is based on the last
statistics notification from uCode; it might not reflect the current
uCode activity. Using "watch" command to monitor the uCode
activity should give up-to-date statistics provided by uCode.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-debug.h   |    3 +
 drivers/net/wireless/iwlwifi/iwl-debugfs.c |  412 ++++++++++++++++++++++++++++
 2 files changed, 415 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index cad5e27..18b8cf7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -100,6 +100,9 @@ struct iwl_debugfs {
 		struct dentry *file_traffic_log;
 		struct dentry *file_rx_queue;
 		struct dentry *file_tx_queue;
+		struct dentry *file_ucode_rx_stats;
+		struct dentry *file_ucode_tx_stats;
+		struct dentry *file_ucode_general_stats;
 	} dbgfs_debug_files;
 	u32 sram_offset;
 	u32 sram_len;
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index d4109cb..20e4edb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -950,11 +950,410 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
 	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,
+				     int bufsz)
+{
+	int p = 0;
+
+	p += scnprintf(buf + p, bufsz - p,
+		"Statistics Flag(0x%X):\n",
+		le32_to_cpu(priv->statistics.flag));
+	if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK)
+		p += scnprintf(buf + p, bufsz - p,
+		"\tStatistics have been cleared\n");
+	p += scnprintf(buf + p, bufsz - p,
+		"\tOperational Frequency: %s\n",
+		(le32_to_cpu(priv->statistics.flag) &
+		UCODE_STATISTICS_FREQUENCY_MSK)
+		 ? "2.4 GHz" : "5.2 GHz");
+	p += scnprintf(buf + p, bufsz - p,
+		"\tTGj Narrow Band: %s\n",
+		(le32_to_cpu(priv->statistics.flag) &
+		UCODE_STATISTICS_NARROW_BAND_MSK)
+		 ? "enabled" : "disabled");
+	return p;
+}
+
+
+static ssize_t iwl_dbgfs_ucode_rx_stats_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;
+	int bufsz = sizeof(struct statistics_rx_phy) * 20 +
+		sizeof(struct statistics_rx_non_phy) * 20 +
+		sizeof(struct statistics_rx_ht_phy) * 20 + 400;
+	ssize_t ret;
+	struct statistics_rx_phy *ofdm;
+	struct statistics_rx_phy *cck;
+	struct statistics_rx_non_phy *general;
+	struct statistics_rx_ht_phy *ht;
+
+	if (!iwl_is_alive(priv))
+		return -EAGAIN;
+
+	/* make request to uCode to retrieve statistics information */
+	mutex_lock(&priv->mutex);
+	ret = iwl_send_statistics_request(priv, 0);
+	mutex_unlock(&priv->mutex);
+
+	if (ret) {
+		IWL_ERR(priv,
+			"Error sending statistics request: %zd\n", ret);
+		return -EAGAIN;
+	}
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	/* the statistic information display here is based on
+	 * the last statistics notification from uCode
+	 * might not reflect the current uCode activity
+	 */
+	ofdm = &priv->statistics.rx.ofdm;
+	cck = &priv->statistics.rx.cck;
+	general = &priv->statistics.rx.general;
+	ht = &priv->statistics.rx.ofdm_ht;
+	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
+	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM:\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n",
+			 le32_to_cpu(ofdm->ina_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n",
+			 le32_to_cpu(ofdm->fina_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
+			 le32_to_cpu(ofdm->plcp_err));
+	pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
+			 le32_to_cpu(ofdm->crc32_err));
+	pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
+			 le32_to_cpu(ofdm->overrun_err));
+	pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
+			 le32_to_cpu(ofdm->early_overrun_err));
+	pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
+			 le32_to_cpu(ofdm->crc32_good));
+	pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n",
+			 le32_to_cpu(ofdm->false_alarm_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n",
+			 le32_to_cpu(ofdm->fina_sync_err_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n",
+			 le32_to_cpu(ofdm->sfd_timeout));
+	pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n",
+			 le32_to_cpu(ofdm->fina_timeout));
+	pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n",
+			 le32_to_cpu(ofdm->unresponded_rts));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"rxe_frame_limit_overrun: %u\n",
+			le32_to_cpu(ofdm->rxe_frame_limit_overrun));
+	pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n",
+			 le32_to_cpu(ofdm->sent_ack_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n",
+			 le32_to_cpu(ofdm->sent_cts_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n",
+			 le32_to_cpu(ofdm->sent_ba_rsp_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n",
+			 le32_to_cpu(ofdm->dsp_self_kill));
+	pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
+			 le32_to_cpu(ofdm->mh_format_err));
+	pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n",
+			 le32_to_cpu(ofdm->re_acq_main_rssi_sum));
+
+	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - CCK:\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n",
+			 le32_to_cpu(cck->ina_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n",
+			 le32_to_cpu(cck->fina_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
+			 le32_to_cpu(cck->plcp_err));
+	pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
+			 le32_to_cpu(cck->crc32_err));
+	pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
+			 le32_to_cpu(cck->overrun_err));
+	pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
+			 le32_to_cpu(cck->early_overrun_err));
+	pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
+			 le32_to_cpu(cck->crc32_good));
+	pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n",
+			 le32_to_cpu(cck->false_alarm_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n",
+			 le32_to_cpu(cck->fina_sync_err_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n",
+			 le32_to_cpu(cck->sfd_timeout));
+	pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n",
+			 le32_to_cpu(cck->fina_timeout));
+	pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n",
+			 le32_to_cpu(cck->unresponded_rts));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"rxe_frame_limit_overrun: %u\n",
+			le32_to_cpu(cck->rxe_frame_limit_overrun));
+	pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n",
+			 le32_to_cpu(cck->sent_ack_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n",
+			 le32_to_cpu(cck->sent_cts_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n",
+			 le32_to_cpu(cck->sent_ba_rsp_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n",
+			 le32_to_cpu(cck->dsp_self_kill));
+	pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
+			 le32_to_cpu(cck->mh_format_err));
+	pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n",
+			 le32_to_cpu(cck->re_acq_main_rssi_sum));
+
+	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - GENERAL:\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts: %u\n",
+			 le32_to_cpu(general->bogus_cts));
+	pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack: %u\n",
+			 le32_to_cpu(general->bogus_ack));
+	pos += scnprintf(buf + pos, bufsz - pos, "non_bssid_frames: %u\n",
+			 le32_to_cpu(general->non_bssid_frames));
+	pos += scnprintf(buf + pos, bufsz - pos, "filtered_frames: %u\n",
+			 le32_to_cpu(general->filtered_frames));
+	pos += scnprintf(buf + pos, bufsz - pos, "non_channel_beacons: %u\n",
+			 le32_to_cpu(general->non_channel_beacons));
+	pos += scnprintf(buf + pos, bufsz - pos, "channel_beacons: %u\n",
+			 le32_to_cpu(general->channel_beacons));
+	pos += scnprintf(buf + pos, bufsz - pos, "num_missed_bcon: %u\n",
+			 le32_to_cpu(general->num_missed_bcon));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"adc_rx_saturation_time: %u\n",
+			le32_to_cpu(general->adc_rx_saturation_time));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"ina_detection_search_time: %u\n",
+			le32_to_cpu(general->ina_detection_search_time));
+	pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_a: %u\n",
+			 le32_to_cpu(general->beacon_silence_rssi_a));
+	pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_b: %u\n",
+			 le32_to_cpu(general->beacon_silence_rssi_b));
+	pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_c: %u\n",
+			 le32_to_cpu(general->beacon_silence_rssi_c));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"interference_data_flag: %u\n",
+			le32_to_cpu(general->interference_data_flag));
+	pos += scnprintf(buf + pos, bufsz - pos, "channel_load: %u\n",
+			 le32_to_cpu(general->channel_load));
+	pos += scnprintf(buf + pos, bufsz - pos, "dsp_false_alarms: %u\n",
+			 le32_to_cpu(general->dsp_false_alarms));
+	pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_a: %u\n",
+			 le32_to_cpu(general->beacon_rssi_a));
+	pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_b: %u\n",
+			 le32_to_cpu(general->beacon_rssi_b));
+	pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_c: %u\n",
+			 le32_to_cpu(general->beacon_rssi_c));
+	pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_a: %u\n",
+			 le32_to_cpu(general->beacon_energy_a));
+	pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_b: %u\n",
+			 le32_to_cpu(general->beacon_energy_b));
+	pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_c: %u\n",
+			 le32_to_cpu(general->beacon_energy_c));
+
+	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
+			 le32_to_cpu(ht->plcp_err));
+	pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
+			 le32_to_cpu(ht->overrun_err));
+	pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
+			 le32_to_cpu(ht->early_overrun_err));
+	pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
+			 le32_to_cpu(ht->crc32_good));
+	pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
+			 le32_to_cpu(ht->crc32_err));
+	pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
+			 le32_to_cpu(ht->mh_format_err));
+	pos += scnprintf(buf + pos, bufsz - pos, "agg_crc32_good: %u\n",
+			 le32_to_cpu(ht->agg_crc32_good));
+	pos += scnprintf(buf + pos, bufsz - pos, "agg_mpdu_cnt: %u\n",
+			 le32_to_cpu(ht->agg_mpdu_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt: %u\n",
+			 le32_to_cpu(ht->agg_cnt));
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_dbgfs_ucode_tx_stats_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;
+	int bufsz = (sizeof(struct statistics_tx) * 24) + 250;
+	ssize_t ret;
+	struct statistics_tx *tx;
+
+	if (!iwl_is_alive(priv))
+		return -EAGAIN;
+
+	/* make request to uCode to retrieve statistics information */
+	mutex_lock(&priv->mutex);
+	ret = iwl_send_statistics_request(priv, 0);
+	mutex_unlock(&priv->mutex);
+
+	if (ret) {
+		IWL_ERR(priv,
+			"Error sending statistics request: %zd\n", ret);
+		return -EAGAIN;
+	}
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	/* the statistic information display here is based on
+	 * the last statistics notification from uCode
+	 * might not reflect the current uCode activity
+	 */
+	tx = &priv->statistics.tx;
+	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
+	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Tx:\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "preamble: %u\n",
+			 le32_to_cpu(tx->preamble_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "rx_detected_cnt: %u\n",
+			 le32_to_cpu(tx->rx_detected_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_defer_cnt: %u\n",
+			 le32_to_cpu(tx->bt_prio_defer_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_kill_cnt: %u\n",
+			 le32_to_cpu(tx->bt_prio_kill_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "few_bytes_cnt: %u\n",
+			 le32_to_cpu(tx->few_bytes_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout: %u\n",
+			 le32_to_cpu(tx->cts_timeout));
+	pos += scnprintf(buf + pos, bufsz - pos, "ack_timeout: %u\n",
+			 le32_to_cpu(tx->ack_timeout));
+	pos += scnprintf(buf + pos, bufsz - pos, "expected_ack_cnt: %u\n",
+			 le32_to_cpu(tx->expected_ack_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "actual_ack_cnt: %u\n",
+			 le32_to_cpu(tx->actual_ack_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "dump_msdu_cnt: %u\n",
+			 le32_to_cpu(tx->dump_msdu_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"burst_abort_next_frame_mismatch_cnt: %u\n",
+			le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"burst_abort_missing_next_frame_cnt: %u\n",
+			le32_to_cpu(tx->burst_abort_missing_next_frame_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout_collision: %u\n",
+			 le32_to_cpu(tx->cts_timeout_collision));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"ack_or_ba_timeout_collision: %u\n",
+			le32_to_cpu(tx->ack_or_ba_timeout_collision));
+	pos += scnprintf(buf + pos, bufsz - pos, "agg ba_timeout: %u\n",
+			 le32_to_cpu(tx->agg.ba_timeout));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"agg ba_reschedule_frames: %u\n",
+			le32_to_cpu(tx->agg.ba_reschedule_frames));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"agg scd_query_agg_frame_cnt: %u\n",
+			le32_to_cpu(tx->agg.scd_query_agg_frame_cnt));
+	pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_no_agg: %u\n",
+			 le32_to_cpu(tx->agg.scd_query_no_agg));
+	pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_agg: %u\n",
+			 le32_to_cpu(tx->agg.scd_query_agg));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"agg scd_query_mismatch: %u\n",
+			le32_to_cpu(tx->agg.scd_query_mismatch));
+	pos += scnprintf(buf + pos, bufsz - pos, "agg frame_not_ready: %u\n",
+			 le32_to_cpu(tx->agg.frame_not_ready));
+	pos += scnprintf(buf + pos, bufsz - pos, "agg underrun: %u\n",
+			 le32_to_cpu(tx->agg.underrun));
+	pos += scnprintf(buf + pos, bufsz - pos, "agg bt_prio_kill: %u\n",
+			 le32_to_cpu(tx->agg.bt_prio_kill));
+	pos += scnprintf(buf + pos, bufsz - pos, "agg rx_ba_rsp_cnt: %u\n",
+			 le32_to_cpu(tx->agg.rx_ba_rsp_cnt));
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_dbgfs_ucode_general_stats_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;
+	int bufsz = sizeof(struct statistics_general) * 4 + 250;
+	ssize_t ret;
+	struct statistics_general *general;
+	struct statistics_dbg *dbg;
+	struct statistics_div *div;
+
+	if (!iwl_is_alive(priv))
+		return -EAGAIN;
+
+	/* make request to uCode to retrieve statistics information */
+	mutex_lock(&priv->mutex);
+	ret = iwl_send_statistics_request(priv, 0);
+	mutex_unlock(&priv->mutex);
+
+	if (ret) {
+		IWL_ERR(priv,
+			"Error sending statistics request: %zd\n", ret);
+		return -EAGAIN;
+	}
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	/* the statistic information display here is based on
+	 * the last statistics notification from uCode
+	 * might not reflect the current uCode activity
+	 */
+	general = &priv->statistics.general;
+	dbg = &priv->statistics.general.dbg;
+	div = &priv->statistics.general.div;
+	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
+	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_General:\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "temperature: %u\n",
+			 le32_to_cpu(general->temperature));
+	pos += scnprintf(buf + pos, bufsz - pos, "temperature_m: %u\n",
+			 le32_to_cpu(general->temperature_m));
+	pos += scnprintf(buf + pos, bufsz - pos, "burst_check: %u\n",
+			 le32_to_cpu(dbg->burst_check));
+	pos += scnprintf(buf + pos, bufsz - pos, "burst_count: %u\n",
+			 le32_to_cpu(dbg->burst_count));
+	pos += scnprintf(buf + pos, bufsz - pos, "sleep_time: %u\n",
+			 le32_to_cpu(general->sleep_time));
+	pos += scnprintf(buf + pos, bufsz - pos, "slots_out: %u\n",
+			 le32_to_cpu(general->slots_out));
+	pos += scnprintf(buf + pos, bufsz - pos, "slots_idle: %u\n",
+			 le32_to_cpu(general->slots_idle));
+	pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp: %u\n",
+			 le32_to_cpu(general->ttl_timestamp));
+	pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a: %u\n",
+			 le32_to_cpu(div->tx_on_a));
+	pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b: %u\n",
+			 le32_to_cpu(div->tx_on_b));
+	pos += scnprintf(buf + pos, bufsz - pos, "exec_time: %u\n",
+			 le32_to_cpu(div->exec_time));
+	pos += scnprintf(buf + pos, bufsz - pos, "probe_time: %u\n",
+			 le32_to_cpu(div->probe_time));
+	pos += scnprintf(buf + pos, bufsz - pos, "rx_enable_counter: %u\n",
+			 le32_to_cpu(general->rx_enable_counter));
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
 DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics);
 DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics);
 DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
 DEBUGFS_READ_FILE_OPS(rx_queue);
 DEBUGFS_READ_FILE_OPS(tx_queue);
+DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
+DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
+DEBUGFS_READ_FILE_OPS(ucode_general_stats);
 
 /*
  * Create the debugfs files and directories
@@ -1001,6 +1400,11 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
 	DEBUGFS_ADD_FILE(traffic_log, debug);
 	DEBUGFS_ADD_FILE(rx_queue, debug);
 	DEBUGFS_ADD_FILE(tx_queue, debug);
+	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_tx_stats, debug);
+		DEBUGFS_ADD_FILE(ucode_general_stats, debug);
+	}
 	DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
 	DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
 			 &priv->disable_chain_noise_cal);
@@ -1045,6 +1449,14 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue);
+	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);
+		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
+			file_ucode_tx_stats);
+		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
+			file_ucode_general_stats);
+	}
 	DEBUGFS_REMOVE(priv->dbgfs->dir_debug);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 07/16] iwlwifi: Display sensitivity and chain noise information
  2009-08-07 22:41 [PATCH 0/16] iwlwifi driver updates 07/08/2009 Reinette Chatre
                   ` (5 preceding siblings ...)
  2009-08-07 22:41 ` [PATCH 06/16] iwlwifi: uCode statistics notification counter Reinette Chatre
@ 2009-08-07 22:41 ` Reinette Chatre
  2009-08-07 22:41 ` [PATCH 08/16] iwlwifi: revert uCode Alive notification with timeout Reinette Chatre
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

Display sensitivity and chain noise data to help understand the current
environment and RF condition.

The data is feeded by statistics notification and Beacon from uCode;
then used by sensitivity calibration and chain noise calibration to
determine how DSP should react to the environment changes

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-debug.h   |    2 +
 drivers/net/wireless/iwlwifi/iwl-debugfs.c |  149 +++++++++++++++++++++++++++-
 2 files changed, 150 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 18b8cf7..82befb7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -103,6 +103,8 @@ struct iwl_debugfs {
 		struct dentry *file_ucode_rx_stats;
 		struct dentry *file_ucode_tx_stats;
 		struct dentry *file_ucode_general_stats;
+		struct dentry *file_sensitivity;
+		struct dentry *file_chain_noise;
 	} dbgfs_debug_files;
 	u32 sram_offset;
 	u32 sram_len;
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 20e4edb..1ad4ff6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -38,7 +38,7 @@
 #include "iwl-debug.h"
 #include "iwl-core.h"
 #include "iwl-io.h"
-
+#include "iwl-calib.h"
 
 /* create and remove of files */
 #define DEBUGFS_ADD_DIR(name, parent) do {                              \
@@ -1346,6 +1346,145 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
 	return ret;
 }
 
+static ssize_t iwl_dbgfs_sensitivity_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;
+	int cnt = 0;
+	char *buf;
+	int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100;
+	ssize_t ret;
+	struct iwl_sensitivity_data *data;
+
+	data = &priv->sensitivity_data;
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
+			data->auto_corr_ofdm);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"auto_corr_ofdm_mrc:\t\t %u\n",
+			data->auto_corr_ofdm_mrc);
+	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
+			data->auto_corr_ofdm_x1);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"auto_corr_ofdm_mrc_x1:\t\t %u\n",
+			data->auto_corr_ofdm_mrc_x1);
+	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
+			data->auto_corr_cck);
+	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
+			data->auto_corr_cck_mrc);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"last_bad_plcp_cnt_ofdm:\t\t %u\n",
+			data->last_bad_plcp_cnt_ofdm);
+	pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
+			data->last_fa_cnt_ofdm);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"last_bad_plcp_cnt_cck:\t\t %u\n",
+			data->last_bad_plcp_cnt_cck);
+	pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
+			data->last_fa_cnt_cck);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
+			data->nrg_curr_state);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
+			data->nrg_prev_state);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
+	for (cnt = 0; cnt < 10; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos, " %u",
+				data->nrg_value[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
+	for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos, " %u",
+				data->nrg_silence_rssi[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
+			data->nrg_silence_ref);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
+			data->nrg_energy_idx);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
+			data->nrg_silence_idx);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
+			data->nrg_th_cck);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"nrg_auto_corr_silence_diff:\t %u\n",
+			data->nrg_auto_corr_silence_diff);
+	pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
+			data->num_in_cck_no_fa);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
+			data->nrg_th_ofdm);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+
+static ssize_t iwl_dbgfs_chain_noise_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;
+	int cnt = 0;
+	char *buf;
+	int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100;
+	ssize_t ret;
+	struct iwl_chain_noise_data *data;
+
+	data = &priv->chain_noise_data;
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
+			data->active_chains);
+	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
+			data->chain_noise_a);
+	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
+			data->chain_noise_b);
+	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
+			data->chain_noise_c);
+	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
+			data->chain_signal_a);
+	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
+			data->chain_signal_b);
+	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
+			data->chain_signal_c);
+	pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
+			data->beacon_count);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
+	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos, " %u",
+				data->disconn_array[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
+	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos, " %u",
+				data->delta_gain_code[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
+			data->radio_write);
+	pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
+			data->state);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
 DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics);
 DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics);
 DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
@@ -1354,6 +1493,8 @@ DEBUGFS_READ_FILE_OPS(tx_queue);
 DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
 DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
 DEBUGFS_READ_FILE_OPS(ucode_general_stats);
+DEBUGFS_READ_FILE_OPS(sensitivity);
+DEBUGFS_READ_FILE_OPS(chain_noise);
 
 /*
  * Create the debugfs files and directories
@@ -1404,6 +1545,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
 		DEBUGFS_ADD_FILE(ucode_rx_stats, debug);
 		DEBUGFS_ADD_FILE(ucode_tx_stats, debug);
 		DEBUGFS_ADD_FILE(ucode_general_stats, debug);
+		DEBUGFS_ADD_FILE(sensitivity, debug);
+		DEBUGFS_ADD_FILE(chain_noise, debug);
 	}
 	DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
 	DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
@@ -1456,6 +1599,10 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
 			file_ucode_tx_stats);
 		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
 			file_ucode_general_stats);
+		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
+			file_sensitivity);
+		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
+			file_chain_noise);
 	}
 	DEBUGFS_REMOVE(priv->dbgfs->dir_debug);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 08/16] iwlwifi: revert uCode Alive notification with timeout
  2009-08-07 22:41 [PATCH 0/16] iwlwifi driver updates 07/08/2009 Reinette Chatre
                   ` (6 preceding siblings ...)
  2009-08-07 22:41 ` [PATCH 07/16] iwlwifi: Display sensitivity and chain noise information Reinette Chatre
@ 2009-08-07 22:41 ` Reinette Chatre
  2009-08-07 22:41 ` [PATCH 09/16] iwlwifi: fix thermal throttling locking problem Reinette Chatre
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Reinette Chatre

From: Reinette Chatre <reinette.chatre@intel.com>

commit "iwlwifi: uCode Alive notification with timeout" introduced a more
reliable mechanism for ucode loading. Unfortunately we hit a problem with
it frequently enough to make a 4965 unusable. The problem can be seen in
debug log below. What this code attempts is to set runtime ucode up to
load, start a timer to wait for the alive response from runtime ucode, and
if it times out it tries again. As can be seen below we receive the alive
response and wake the waiting task _before_ the tasks starts waiting. The
task thus times out as the alive response is not received while it is
waiting for it and it restarts the device. This starts the cycle all over
again.

[29739.000819] ieee80211 phy0: U iwl_mac_start enter
[29739.005751] ieee80211 phy0: U iwl_prepare_card_hw iwl_prepare_card_hw enter
[29739.012798] ieee80211 phy0: U iwl_set_hw_ready hardware ready
[29739.057200] ieee80211 phy0: U iwl4965_load_bsm Begin load bsm
[29739.063366] ieee80211 phy0: U iwl4965_verify_bsm Begin verify bsm
[29739.072485] ieee80211 phy0: U iwl4965_verify_bsm BSM bootstrap uCode image OK
[29739.079671] ieee80211 phy0: U iwl4965_load_bsm BSM write complete, poll 0 iterations
[29739.257019] ieee80211 phy0: I iwl_rx_reply_alive Alive ucode status 0x00000001 revision 0x1 0x9
[29739.260964] ieee80211 phy0: I iwl_rx_reply_alive Initialization Alive received.
[29739.260964] ieee80211 phy0: U __iwl_up iwlagn is coming up
[29739.278571] ieee80211 phy0: U iwl_mac_start Start UP work done.
[29739.284509] ieee80211 phy0: U iwlcore_verify_inst_sparse ucode inst image size is 788
[29739.292432] ieee80211 phy0: U iwlcore_verify_inst_sparse ucode inst image size is 10312
[29739.302004] ieee80211 phy0: U iwl_verify_ucode Initialize uCode is good in inst SRAM
[29739.309746] ieee80211 phy0: U iwl4965_hw_get_temperature Running temperature calibration
[29739.317833] ieee80211 phy0: U iwl4965_hw_get_temperature Calib values R[1-3]: -36 13522 -13496 R4: -2726
[29739.327337] ieee80211 phy0: U iwl4965_hw_get_temperature Calibrated temperature: 310K, 37C
[29739.335598] ieee80211 phy0: U iwl4965_init_alive_start Initialization Alive received.
[29739.343477] ieee80211 phy0: U iwl4965_set_ucode_ptrs Runtime uCode pointers are set.
[29739.351283] ieee80211 phy0: I iwl_rx_reply_alive Alive ucode status 0x00000001 revision 0x1 0x0
[29739.355210] ieee80211 phy0: I iwl_rx_reply_alive Runtime Alive received.
[29739.366731] iwlagn 0000:03:00.0: Runtime uCode already alive? Waiting for alive anyway
[29743.284110] iwlagn 0000:03:00.0: START_ALIVE timeout after 4000ms.
[29743.290337] ieee80211 phy0: U iwl_mac_add_interface enter: type 2
[29744.364089] iwlagn 0000:03:00.0: Runtime timeout after 5000ms
[29744.370882] ieee80211 phy0: U iwl_alive_start Runtime Alive received.
[29744.377347] ieee80211 phy0: U iwlcore_verify_inst_sparse ucode inst image size is 788
[29744.385287] ieee80211 phy0: U iwlcore_verify_inst_sparse ucode inst image size is 10312
[29744.393397] ieee80211 phy0: U iwlcore_verify_inst_sparse ucode inst image size is 94720
[29744.415835] ieee80211 phy0: U iwl_verify_ucode Runtime uCode is good in inst SRAM

Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-4965.c |   26 +---------------
 drivers/net/wireless/iwlwifi/iwl-agn.c  |   50 -------------------------------
 drivers/net/wireless/iwlwifi/iwl-core.c |   39 +++++------------------
 drivers/net/wireless/iwlwifi/iwl-core.h |    2 -
 drivers/net/wireless/iwlwifi/iwl-dev.h  |    2 -
 5 files changed, 10 insertions(+), 109 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index f02023e..e427a89 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -146,7 +146,7 @@ static int iwl4965_load_bsm(struct iwl_priv *priv)
 
 	IWL_DEBUG_INFO(priv, "Begin load bsm\n");
 
-	priv->ucode_type = UCODE_INIT;
+	priv->ucode_type = UCODE_RT;
 
 	/* make sure bootstrap program is no larger than BSM's SRAM size */
 	if (len > IWL49_MAX_BSM_SIZE)
@@ -256,8 +256,6 @@ static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)
 */
 static void iwl4965_init_alive_start(struct iwl_priv *priv)
 {
-	int ret;
-
 	/* Check alive response for "valid" sign from uCode */
 	if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
 		/* We had an error bringing up the hardware, so take it
@@ -289,28 +287,6 @@ static void iwl4965_init_alive_start(struct iwl_priv *priv)
 		IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n");
 		goto restart;
 	}
-	priv->ucode_type = UCODE_RT;
-	if (test_bit(STATUS_RT_UCODE_ALIVE, &priv->status)) {
-		IWL_WARN(priv, "Runtime uCode already alive? "
-			"Waiting for alive anyway\n");
-		clear_bit(STATUS_RT_UCODE_ALIVE, &priv->status);
-	}
-	ret = wait_event_interruptible_timeout(
-			priv->wait_command_queue,
-			test_bit(STATUS_RT_UCODE_ALIVE, &priv->status),
-			UCODE_ALIVE_TIMEOUT);
-	if (!ret) {
-		/* FIXME: if STATUS_RT_UCODE_ALIVE timeout
-		 * go back to restart the download Init uCode again
-		 * this might cause to trap in the restart loop
-		 */
-		priv->ucode_type = UCODE_NONE;
-		if (!test_bit(STATUS_RT_UCODE_ALIVE, &priv->status)) {
-			IWL_ERR(priv, "Runtime timeout after %dms\n",
-				jiffies_to_msecs(UCODE_ALIVE_TIMEOUT));
-			goto restart;
-		}
-	}
 	return;
 
 restart:
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index c9a1aac..319df4a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -533,16 +533,12 @@ static void iwl_rx_reply_alive(struct iwl_priv *priv,
 
 	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
 		IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
-		set_bit(STATUS_INIT_UCODE_ALIVE, &priv->status);
-		wake_up_interruptible(&priv->wait_command_queue);
 		memcpy(&priv->card_alive_init,
 		       &pkt->u.alive_frame,
 		       sizeof(struct iwl_init_alive_resp));
 		pwork = &priv->init_alive_start;
 	} else {
 		IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
-		set_bit(STATUS_RT_UCODE_ALIVE, &priv->status);
-		wake_up_interruptible(&priv->wait_command_queue);
 		memcpy(&priv->card_alive, &pkt->u.alive_frame,
 		       sizeof(struct iwl_alive_resp));
 		pwork = &priv->alive_start;
@@ -1784,7 +1780,6 @@ static int __iwl_up(struct iwl_priv *priv)
 {
 	int i;
 	int ret;
-	unsigned long status;
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
 		IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
@@ -1862,51 +1857,6 @@ static int __iwl_up(struct iwl_priv *priv)
 		/* start card; "initialize" will load runtime ucode */
 		iwl_nic_start(priv);
 
-		/* Just finish download Init or Runtime uCode image to device
-		 * now we wait here for uCode send REPLY_ALIVE notification
-		 * to indicate uCode is ready.
-		 * 1) For Init uCode image, all iwlagn devices should wait here
-		 * on STATUS_INIT_UCODE_ALIVE status bit; if timeout before
-		 * receive the REPLY_ALIVE notification, go back and try to
-		 * download the Init uCode image again.
-		 * 2) For Runtime uCode image, all iwlagn devices except 4965
-		 * wait here on STATUS_RT_UCODE_ALIVE status bit; if
-		 * timeout before receive the REPLY_ALIVE notification, go back
-		 * and download the Runtime uCode image again.
-		 * 3) For 4965 Runtime uCode, it will not go through this path,
-		 * need to wait for STATUS_RT_UCODE_ALIVE status bit in
-		 * iwl4965_init_alive_start() function; if timeout, need to
-		 * restart and download Init uCode image.
-		 */
-		if (priv->ucode_type == UCODE_INIT)
-			status = STATUS_INIT_UCODE_ALIVE;
-		else
-			status = STATUS_RT_UCODE_ALIVE;
-		if (test_bit(status, &priv->status)) {
-			IWL_WARN(priv,
-				"%s uCode already alive? "
-				"Waiting for alive anyway\n",
-				(status == STATUS_INIT_UCODE_ALIVE)
-				? "INIT" : "Runtime");
-			clear_bit(status, &priv->status);
-		}
-		ret = wait_event_interruptible_timeout(
-				priv->wait_command_queue,
-				test_bit(status, &priv->status),
-				UCODE_ALIVE_TIMEOUT);
-		if (!ret) {
-			if (!test_bit(status, &priv->status)) {
-				priv->ucode_type =
-					(status == STATUS_INIT_UCODE_ALIVE)
-					? UCODE_NONE : UCODE_INIT;
-				IWL_ERR(priv,
-					"%s timeout after %dms\n",
-					(status == STATUS_INIT_UCODE_ALIVE)
-					? "INIT" : "Runtime",
-					jiffies_to_msecs(UCODE_ALIVE_TIMEOUT));
-				continue;
-			}
-		}
 		IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n");
 
 		return 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 202bc39..79170a9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1343,17 +1343,10 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv)
 	u32 desc, time, count, base, data1;
 	u32 blink1, blink2, ilink1, ilink2;
 
-	switch (priv->ucode_type) {
-	case UCODE_RT:
-		base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
-		break;
-	case UCODE_INIT:
+	if (priv->ucode_type == UCODE_INIT)
 		base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
-		break;
-	default:
-		IWL_ERR(priv, "uCode image not available\n");
-		return;
-	}
+	else
+		base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
 
 	if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
 		IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
@@ -1405,17 +1398,10 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
 
 	if (num_events == 0)
 		return;
-	switch (priv->ucode_type) {
-	case UCODE_RT:
-		base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-		break;
-	case UCODE_INIT:
+	if (priv->ucode_type == UCODE_INIT)
 		base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
-		break;
-	default:
-		IWL_ERR(priv, "uCode image not available\n");
-		return;
-	}
+	else
+		base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
 
 	if (mode == 0)
 		event_size = 2 * sizeof(u32);
@@ -1452,17 +1438,10 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv)
 	u32 next_entry; /* index of next entry to be written by uCode */
 	u32 size;       /* # entries that we'll print */
 
-	switch (priv->ucode_type) {
-	case UCODE_RT:
-		base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-		break;
-	case UCODE_INIT:
+	if (priv->ucode_type == UCODE_INIT)
 		base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
-		break;
-	default:
-		IWL_ERR(priv, "uCode image not available\n");
-		return;
-	}
+	else
+		base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
 
 	if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
 		IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index fc096b9..ea8748d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -547,8 +547,6 @@ void iwlcore_free_geos(struct iwl_priv *priv);
 #define STATUS_POWER_PMI	16
 #define STATUS_FW_ERROR		17
 #define STATUS_MODE_PENDING	18
-#define STATUS_INIT_UCODE_ALIVE	19
-#define STATUS_RT_UCODE_ALIVE	20
 
 
 static inline int iwl_is_ready(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index dcf9d57..61f9523 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -823,8 +823,6 @@ struct iwl_calib_result {
 	size_t buf_len;
 };
 
-#define UCODE_ALIVE_TIMEOUT	(5 * HZ)
-
 enum ucode_type {
 	UCODE_NONE = 0,
 	UCODE_INIT,
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 09/16] iwlwifi: fix thermal throttling locking problem
  2009-08-07 22:41 [PATCH 0/16] iwlwifi driver updates 07/08/2009 Reinette Chatre
                   ` (7 preceding siblings ...)
  2009-08-07 22:41 ` [PATCH 08/16] iwlwifi: revert uCode Alive notification with timeout Reinette Chatre
@ 2009-08-07 22:41 ` Reinette Chatre
  2009-08-07 22:41 ` [PATCH 10/16] iwlwifi: fix legacy thermal throttling power index Reinette Chatre
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

Move all the thermal throttling functions to background task to make
sure do not change power and rx chain in interrupt handler.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-dev.h   |    3 ++
 drivers/net/wireless/iwlwifi/iwl-power.c |   57 +++++++++++++++++++++++++++--
 2 files changed, 56 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 61f9523..35d07a8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1197,6 +1197,9 @@ struct iwl_priv {
 	struct work_struct report_work;
 	struct work_struct request_scan;
 	struct work_struct beacon_update;
+	struct work_struct tt_work;
+	struct work_struct ct_enter;
+	struct work_struct ct_exit;
 
 	struct tasklet_struct irq_tasklet;
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 594b5c2..9c05af7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -481,6 +481,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
 			tt->tt_power_mode = IWL_POWER_INDEX_5;
 			break;
 		}
+		mutex_lock(&priv->mutex);
 		if (iwl_power_update_mode(priv, true)) {
 			/* TT state not updated
 			 * try again during next temperature read
@@ -499,6 +500,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
 			IWL_DEBUG_POWER(priv, "Power Index change to %u\n",
 					tt->tt_power_mode);
 		}
+		mutex_unlock(&priv->mutex);
 	}
 }
 
@@ -609,6 +611,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
 			 * in case get disabled before */
 			iwl_set_rxon_ht(priv, &priv->current_ht_config);
 		}
+		mutex_lock(&priv->mutex);
 		if (iwl_power_update_mode(priv, true)) {
 			/* TT state not updated
 			 * try again during next temperature read
@@ -631,6 +634,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
 				iwl_perform_ct_kill_task(priv, false);
 			}
 		}
+		mutex_unlock(&priv->mutex);
 	}
 }
 
@@ -644,13 +648,17 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
  * for advance mode
  * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state
  */
-void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
+static void iwl_bg_ct_enter(struct work_struct *work)
 {
+	struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter);
 	struct iwl_tt_mgmt *tt = &priv->power_data.tt;
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
+	if (!iwl_is_ready(priv))
+		return;
+
 	if (tt->state != IWL_TI_CT_KILL) {
 		IWL_ERR(priv, "Device reached critical temperature "
 			      "- ucode going to sleep!\n");
@@ -662,20 +670,23 @@ void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
 					       CT_KILL_THRESHOLD + 1);
 	}
 }
-EXPORT_SYMBOL(iwl_tt_enter_ct_kill);
 
 /* Card State Notification indicated out of critical temperature
  * since Card State Notification will not provide any temperature reading
  * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature
  * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state
  */
-void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
+static void iwl_bg_ct_exit(struct work_struct *work)
 {
+	struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit);
 	struct iwl_tt_mgmt *tt = &priv->power_data.tt;
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
+	if (!iwl_is_ready(priv))
+		return;
+
 	/* stop ct_kill_exit_tm timer */
 	del_timer_sync(&priv->power_data.ct_kill_exit_tm);
 
@@ -690,10 +701,30 @@ void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
 			iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD);
 	}
 }
+
+void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
+{
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n");
+	queue_work(priv->workqueue, &priv->ct_enter);
+}
+EXPORT_SYMBOL(iwl_tt_enter_ct_kill);
+
+void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
+{
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n");
+	queue_work(priv->workqueue, &priv->ct_exit);
+}
 EXPORT_SYMBOL(iwl_tt_exit_ct_kill);
 
-void iwl_tt_handler(struct iwl_priv *priv)
+static void iwl_bg_tt_work(struct work_struct *work)
 {
+	struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work);
 	s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
@@ -707,6 +738,15 @@ void iwl_tt_handler(struct iwl_priv *priv)
 	else
 		iwl_advance_tt_handler(priv, temp);
 }
+
+void iwl_tt_handler(struct iwl_priv *priv)
+{
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n");
+	queue_work(priv->workqueue, &priv->tt_work);
+}
 EXPORT_SYMBOL(iwl_tt_handler);
 
 /* Thermal throttling initialization
@@ -731,6 +771,12 @@ void iwl_tt_initialize(struct iwl_priv *priv)
 	init_timer(&priv->power_data.ct_kill_exit_tm);
 	priv->power_data.ct_kill_exit_tm.data = (unsigned long)priv;
 	priv->power_data.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill;
+
+	/* setup deferred ct kill work */
+	INIT_WORK(&priv->tt_work, iwl_bg_tt_work);
+	INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
+	INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
+
 	switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
 	case CSR_HW_REV_TYPE_6x00:
 	case CSR_HW_REV_TYPE_6x50:
@@ -782,6 +828,9 @@ void iwl_tt_exit(struct iwl_priv *priv)
 
 	/* stop ct_kill_exit_tm timer if activated */
 	del_timer_sync(&priv->power_data.ct_kill_exit_tm);
+	cancel_work_sync(&priv->tt_work);
+	cancel_work_sync(&priv->ct_enter);
+	cancel_work_sync(&priv->ct_exit);
 
 	if (priv->power_data.adv_tt) {
 		/* free advance thermal throttling memory */
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 10/16] iwlwifi: fix legacy thermal throttling power index
  2009-08-07 22:41 [PATCH 0/16] iwlwifi driver updates 07/08/2009 Reinette Chatre
                   ` (8 preceding siblings ...)
  2009-08-07 22:41 ` [PATCH 09/16] iwlwifi: fix thermal throttling locking problem Reinette Chatre
@ 2009-08-07 22:41 ` Reinette Chatre
  2009-08-07 22:41 ` [PATCH 11/16] iwlwifi: handle the case when set power fail Reinette Chatre
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

For legacy thermal throttling, set the new Thermal Throttling
state and change power index when thermal throttling manager detects
temperature changed. The current implementation sets the state to the
previous Thermal Throttling state, which causes system to enter wrong
power index. The worse case, it will trying to set the
lower power index when device reach critical temperature, it will cuase
issue for both system and the device.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-power.c |   25 +++++++++++++------------
 1 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 9c05af7..bd97a0d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -425,7 +425,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
 static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
 {
 	struct iwl_tt_mgmt *tt = &priv->power_data.tt;
-	enum iwl_tt_state new_state;
+	enum iwl_tt_state old_state;
 	struct iwl_power_mgr *setting = &priv->power_data;
 
 #ifdef CONFIG_IWLWIFI_DEBUG
@@ -438,26 +438,27 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
 			(temp - tt->tt_previous_temp));
 	}
 #endif
+	old_state = tt->state;
 	/* in Celsius */
 	if (temp >= IWL_MINIMAL_POWER_THRESHOLD)
-		new_state = IWL_TI_CT_KILL;
+		tt->state = IWL_TI_CT_KILL;
 	else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2)
-		new_state = IWL_TI_2;
+		tt->state = IWL_TI_2;
 	else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1)
-		new_state = IWL_TI_1;
+		tt->state = IWL_TI_1;
 	else
-		new_state = IWL_TI_0;
+		tt->state = IWL_TI_0;
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 	tt->tt_previous_temp = temp;
 #endif
-	if (tt->state != new_state) {
-		if (tt->state == IWL_TI_0) {
+	if (tt->state != old_state) {
+		if (old_state == IWL_TI_0) {
 			tt->sys_power_mode = setting->power_mode;
 			IWL_DEBUG_POWER(priv, "current power mode: %u\n",
 				setting->power_mode);
 		}
-		switch (new_state) {
+		switch (tt->state) {
 		case IWL_TI_0:
 			/* when system ready to go back to IWL_TI_0 state
 			 * using system power mode instead of TT power mode
@@ -486,15 +487,15 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
 			/* TT state not updated
 			 * try again during next temperature read
 			 */
+			tt->state = old_state;
 			IWL_ERR(priv, "Cannot update power mode, "
 					"TT state not updated\n");
 		} else {
-			if (new_state == IWL_TI_CT_KILL)
+			if (tt->state == IWL_TI_CT_KILL)
 				iwl_perform_ct_kill_task(priv, true);
-			else if (tt->state == IWL_TI_CT_KILL &&
-				 new_state != IWL_TI_CT_KILL)
+			else if (old_state == IWL_TI_CT_KILL &&
+				 tt->state != IWL_TI_CT_KILL)
 				iwl_perform_ct_kill_task(priv, false);
-			tt->state = new_state;
 			IWL_DEBUG_POWER(priv, "Temperature state changed %u\n",
 					tt->state);
 			IWL_DEBUG_POWER(priv, "Power Index change to %u\n",
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 11/16] iwlwifi: handle the case when set power fail
  2009-08-07 22:41 [PATCH 0/16] iwlwifi driver updates 07/08/2009 Reinette Chatre
                   ` (9 preceding siblings ...)
  2009-08-07 22:41 ` [PATCH 10/16] iwlwifi: fix legacy thermal throttling power index Reinette Chatre
@ 2009-08-07 22:41 ` Reinette Chatre
  2009-08-07 22:41 ` [PATCH 12/16] iwlwifi: refactor some thermal throttle code Reinette Chatre
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

Modify the power update function, when driver fail to set the power, it
should not continue move forward and try to change the rx chain
configuration.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-power.c |   21 ++++++++++++---------
 1 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index bd97a0d..9e8916d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -282,18 +282,21 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
 			cmd.flags |= IWL_POWER_FAST_PD;
 
 		ret = iwl_set_power(priv, &cmd);
-
-		if (final_mode == IWL_POWER_MODE_CAM)
-			clear_bit(STATUS_POWER_PMI, &priv->status);
-
-		if (priv->cfg->ops->lib->update_chain_flags && update_chains)
-			priv->cfg->ops->lib->update_chain_flags(priv);
-		else
-			IWL_DEBUG_POWER(priv, "Cannot update the power, chain noise "
+		if (!ret) {
+			if (final_mode == IWL_POWER_MODE_CAM)
+				clear_bit(STATUS_POWER_PMI, &priv->status);
+
+			if (priv->cfg->ops->lib->update_chain_flags &&
+			    update_chains)
+				priv->cfg->ops->lib->update_chain_flags(priv);
+			else
+				IWL_DEBUG_POWER(priv,
+					"Cannot update the power, chain noise "
 					"calibration running: %d\n",
 					priv->chain_noise_data.state);
-		if (!ret)
 			setting->power_mode = final_mode;
+		} else
+			IWL_ERR(priv, "set power fail, ret = %d", ret);
 	}
 
 	return ret;
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 12/16] iwlwifi: refactor some thermal throttle code
  2009-08-07 22:41 [PATCH 0/16] iwlwifi driver updates 07/08/2009 Reinette Chatre
                   ` (10 preceding siblings ...)
  2009-08-07 22:41 ` [PATCH 11/16] iwlwifi: handle the case when set power fail Reinette Chatre
@ 2009-08-07 22:41 ` Reinette Chatre
  2009-08-07 22:41 ` [PATCH 13/16] iwlwifi: fix missing EXPORT_SYMBOL Reinette Chatre
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Reinette Chatre

From: Johannes Berg <johannes@sipsolutions.net>

Some of the thermal throttle data structures and code
are really very intermingled with the sleep (power)
control code. They really do belong together in a way
since the thermal throttle code uses powersaving to
achieve its goal, but it's making it hard to work on
the powersave code. Split this up to make that easier.
I've also changed the antenna defines to an enum and
used the same enum for RX and TX.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn-rs.c  |   14 +++---
 drivers/net/wireless/iwlwifi/iwl-core.c    |    2 +-
 drivers/net/wireless/iwlwifi/iwl-debugfs.c |    7 +--
 drivers/net/wireless/iwlwifi/iwl-dev.h     |    1 +
 drivers/net/wireless/iwlwifi/iwl-power.c   |   78 ++++++++++++++--------------
 drivers/net/wireless/iwlwifi/iwl-power.h   |   50 +++++++++---------
 6 files changed, 76 insertions(+), 76 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 0c3ed23..2133155 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -1401,7 +1401,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
 	if (!iwl_ht_enabled(priv))
 		/* stay in Legacy */
 		tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
-	else if (iwl_tx_ant_restriction(priv) == IWL_TX_SINGLE &&
+	else if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE &&
 		   tbl->action > IWL_LEGACY_SWITCH_SISO)
 		tbl->action = IWL_LEGACY_SWITCH_SISO;
 	for (; ;) {
@@ -1535,7 +1535,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
 	u8 update_search_tbl_counter = 0;
 	int ret;
 
-	if (iwl_tx_ant_restriction(priv) == IWL_TX_SINGLE &&
+	if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE &&
 	    tbl->action > IWL_SISO_SWITCH_ANTENNA2) {
 		/* stay in SISO */
 		tbl->action = IWL_SISO_SWITCH_ANTENNA1;
@@ -1674,7 +1674,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
 	u8 update_search_tbl_counter = 0;
 	int ret;
 
-	if ((iwl_tx_ant_restriction(priv) == IWL_TX_SINGLE) &&
+	if ((iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE) &&
 	    (tbl->action < IWL_MIMO2_SWITCH_SISO_A ||
 	     tbl->action > IWL_MIMO2_SWITCH_SISO_C)) {
 		/* switch in SISO */
@@ -1816,7 +1816,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
 	int ret;
 	u8 update_search_tbl_counter = 0;
 
-	if ((iwl_tx_ant_restriction(priv) == IWL_TX_SINGLE) &&
+	if ((iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE) &&
 	    (tbl->action < IWL_MIMO3_SWITCH_SISO_A ||
 	     tbl->action > IWL_MIMO3_SWITCH_SISO_C)) {
 		/* switch in SISO */
@@ -2202,7 +2202,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
 
 	/* If we are searching for better modulation mode, check success. */
 	if (lq_sta->search_better_tbl &&
-	    (iwl_tx_ant_restriction(priv) == IWL_TX_MULTI)) {
+	    (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI)) {
 		/* If good success, continue using the "search" mode;
 		 * no need to send new link quality command, since we're
 		 * continuing to use the setup that we've been trying. */
@@ -2332,7 +2332,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
 		scale_action = 0;
 	if (!iwl_ht_enabled(priv) && !is_legacy(tbl->lq_type))
 		scale_action = -1;
-	if (iwl_tx_ant_restriction(priv) != IWL_TX_MULTI &&
+	if (iwl_tx_ant_restriction(priv) != IWL_ANT_OK_MULTI &&
 		(is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type)))
 		scale_action = -1;
 	switch (scale_action) {
@@ -2368,7 +2368,7 @@ lq_update:
 		rate = rs_update_rate_tbl(priv, lq_sta,
 					  tbl, index, is_green);
 
-	if (iwl_tx_ant_restriction(priv) == IWL_TX_MULTI) {
+	if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) {
 		/* Should we stay with this modulation mode,
 		 * or search for a new one? */
 		rs_stay_in_table(lq_sta);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 79170a9..22961e9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -2214,7 +2214,7 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv)
 	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
 		    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
 	spin_unlock_irqrestore(&priv->lock, flags);
-	priv->power_data.ct_kill_toggle = false;
+	priv->thermal_throttle.ct_kill_toggle = false;
 
 	switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
 	case CSR_HW_REV_TYPE_1000:
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 1ad4ff6..7b578d4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -704,7 +704,7 @@ static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
 				size_t count, loff_t *ppos)
 {
 	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
-	struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 	struct iwl_tt_restriction *restriction;
 	char buf[100];
 	int pos = 0;
@@ -713,12 +713,11 @@ static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
 
 	pos += scnprintf(buf + pos, bufsz - pos,
 			"Thermal Throttling Mode: %s\n",
-			(priv->power_data.adv_tt)
-			? "Advance" : "Legacy");
+			tt->advanced_tt ? "Advance" : "Legacy");
 	pos += scnprintf(buf + pos, bufsz - pos,
 			"Thermal Throttling State: %d\n",
 			tt->state);
-	if (priv->power_data.adv_tt) {
+	if (tt->advanced_tt) {
 		restriction = tt->restriction + tt->state;
 		pos += scnprintf(buf + pos, bufsz - pos,
 				"Tx mode: %d\n",
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 35d07a8..1aa2ae6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1111,6 +1111,7 @@ struct iwl_priv {
 	struct isr_statistics isr_stats;
 
 	struct iwl_power_mgr power_data;
+	struct iwl_tt_mgmt thermal_throttle;
 
 	struct iwl_notif_statistics statistics;
 	unsigned long last_statistics_time;
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 9e8916d..27ad59d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -132,10 +132,10 @@ static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = {
 
 /* Advance Thermal Throttling default restriction table */
 static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = {
-	{IWL_TX_MULTI, true, IWL_RX_MULTI},
-	{IWL_TX_SINGLE, true, IWL_RX_MULTI},
-	{IWL_TX_SINGLE, false, IWL_RX_SINGLE},
-	{IWL_TX_NONE, false, IWL_RX_NONE}
+	{IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true },
+	{IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true },
+	{IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false },
+	{IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false }
 };
 
 /* set card power command */
@@ -251,7 +251,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
 {
 	struct iwl_power_mgr *setting = &(priv->power_data);
 	int ret = 0;
-	struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 	u16 uninitialized_var(final_mode);
 	bool update_chains;
 
@@ -317,35 +317,35 @@ EXPORT_SYMBOL(iwl_power_set_user_mode);
 
 bool iwl_ht_enabled(struct iwl_priv *priv)
 {
-	struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 	struct iwl_tt_restriction *restriction;
 
-	if (!priv->power_data.adv_tt)
+	if (!priv->thermal_throttle.advanced_tt)
 		return true;
 	restriction = tt->restriction + tt->state;
 	return restriction->is_ht;
 }
 EXPORT_SYMBOL(iwl_ht_enabled);
 
-u8 iwl_tx_ant_restriction(struct iwl_priv *priv)
+enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv)
 {
-	struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 	struct iwl_tt_restriction *restriction;
 
-	if (!priv->power_data.adv_tt)
-		return IWL_TX_MULTI;
+	if (!priv->thermal_throttle.advanced_tt)
+		return IWL_ANT_OK_MULTI;
 	restriction = tt->restriction + tt->state;
 	return restriction->tx_stream;
 }
 EXPORT_SYMBOL(iwl_tx_ant_restriction);
 
-u8 iwl_rx_ant_restriction(struct iwl_priv *priv)
+enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv)
 {
-	struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 	struct iwl_tt_restriction *restriction;
 
-	if (!priv->power_data.adv_tt)
-		return IWL_RX_MULTI;
+	if (!priv->thermal_throttle.advanced_tt)
+		return IWL_ANT_OK_MULTI;
 	restriction = tt->restriction + tt->state;
 	return restriction->rx_stream;
 }
@@ -364,21 +364,21 @@ EXPORT_SYMBOL(iwl_rx_ant_restriction);
 static void iwl_tt_check_exit_ct_kill(unsigned long data)
 {
 	struct iwl_priv *priv = (struct iwl_priv *)data;
-	struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 	unsigned long flags;
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
 	if (tt->state == IWL_TI_CT_KILL) {
-		if (priv->power_data.ct_kill_toggle) {
+		if (priv->thermal_throttle.ct_kill_toggle) {
 			iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
 				    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
-			priv->power_data.ct_kill_toggle = false;
+			priv->thermal_throttle.ct_kill_toggle = false;
 		} else {
 			iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
 				    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
-			priv->power_data.ct_kill_toggle = true;
+			priv->thermal_throttle.ct_kill_toggle = true;
 		}
 		iwl_read32(priv, CSR_UCODE_DRV_GP1);
 		spin_lock_irqsave(&priv->reg_lock, flags);
@@ -389,7 +389,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
 		/* Reschedule the ct_kill timer to occur in
 		 * CT_KILL_EXIT_DURATION seconds to ensure we get a
 		 * thermal update */
-		mod_timer(&priv->power_data.ct_kill_exit_tm, jiffies +
+		mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies +
 			  CT_KILL_EXIT_DURATION * HZ);
 	}
 }
@@ -403,7 +403,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
 			ieee80211_stop_queues(priv->hw);
 		IWL_DEBUG_POWER(priv,
 				"Schedule 5 seconds CT_KILL Timer\n");
-		mod_timer(&priv->power_data.ct_kill_exit_tm, jiffies +
+		mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies +
 			  CT_KILL_EXIT_DURATION * HZ);
 	} else {
 		IWL_DEBUG_POWER(priv, "Wake all queues\n");
@@ -427,7 +427,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
  */
 static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
 {
-	struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 	enum iwl_tt_state old_state;
 	struct iwl_power_mgr *setting = &priv->power_data;
 
@@ -531,7 +531,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
  */
 static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
 {
-	struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 	int i;
 	bool changed = false;
 	enum iwl_tt_state old_state;
@@ -655,7 +655,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
 static void iwl_bg_ct_enter(struct work_struct *work)
 {
 	struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter);
-	struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
@@ -666,7 +666,7 @@ static void iwl_bg_ct_enter(struct work_struct *work)
 	if (tt->state != IWL_TI_CT_KILL) {
 		IWL_ERR(priv, "Device reached critical temperature "
 			      "- ucode going to sleep!\n");
-		if (!priv->power_data.adv_tt)
+		if (!priv->thermal_throttle.advanced_tt)
 			iwl_legacy_tt_handler(priv,
 					      IWL_MINIMAL_POWER_THRESHOLD);
 		else
@@ -683,7 +683,7 @@ static void iwl_bg_ct_enter(struct work_struct *work)
 static void iwl_bg_ct_exit(struct work_struct *work)
 {
 	struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit);
-	struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
@@ -692,13 +692,13 @@ static void iwl_bg_ct_exit(struct work_struct *work)
 		return;
 
 	/* stop ct_kill_exit_tm timer */
-	del_timer_sync(&priv->power_data.ct_kill_exit_tm);
+	del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
 
 	if (tt->state == IWL_TI_CT_KILL) {
 		IWL_ERR(priv,
 			"Device temperature below critical"
 			"- ucode awake!\n");
-		if (!priv->power_data.adv_tt)
+		if (!priv->thermal_throttle.advanced_tt)
 			iwl_legacy_tt_handler(priv,
 					IWL_REDUCED_PERFORMANCE_THRESHOLD_2);
 		else
@@ -737,7 +737,7 @@ static void iwl_bg_tt_work(struct work_struct *work)
 	if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
 		temp = KELVIN_TO_CELSIUS(priv->temperature);
 
-	if (!priv->power_data.adv_tt)
+	if (!priv->thermal_throttle.advanced_tt)
 		iwl_legacy_tt_handler(priv, temp);
 	else
 		iwl_advance_tt_handler(priv, temp);
@@ -760,7 +760,7 @@ EXPORT_SYMBOL(iwl_tt_handler);
  */
 void iwl_tt_initialize(struct iwl_priv *priv)
 {
-	struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 	struct iwl_power_mgr *setting = &priv->power_data;
 	int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
 	struct iwl_tt_trans *transaction;
@@ -772,9 +772,9 @@ void iwl_tt_initialize(struct iwl_priv *priv)
 	tt->state = IWL_TI_0;
 	tt->sys_power_mode = setting->power_mode;
 	tt->tt_power_mode = tt->sys_power_mode;
-	init_timer(&priv->power_data.ct_kill_exit_tm);
-	priv->power_data.ct_kill_exit_tm.data = (unsigned long)priv;
-	priv->power_data.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill;
+	init_timer(&priv->thermal_throttle.ct_kill_exit_tm);
+	priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv;
+	priv->thermal_throttle.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill;
 
 	/* setup deferred ct kill work */
 	INIT_WORK(&priv->tt_work, iwl_bg_tt_work);
@@ -792,7 +792,7 @@ void iwl_tt_initialize(struct iwl_priv *priv)
 			GFP_KERNEL);
 		if (!tt->restriction || !tt->transaction) {
 			IWL_ERR(priv, "Fallback to Legacy Throttling\n");
-			priv->power_data.adv_tt = false;
+			priv->thermal_throttle.advanced_tt = false;
 			kfree(tt->restriction);
 			tt->restriction = NULL;
 			kfree(tt->transaction);
@@ -814,12 +814,12 @@ void iwl_tt_initialize(struct iwl_priv *priv)
 				IWL_TI_STATE_MAX;
 			memcpy(tt->restriction,
 				&restriction_range[0], size);
-			priv->power_data.adv_tt = true;
+			priv->thermal_throttle.advanced_tt = true;
 		}
 		break;
 	default:
 		IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n");
-		priv->power_data.adv_tt = false;
+		priv->thermal_throttle.advanced_tt = false;
 		break;
 	}
 }
@@ -828,15 +828,15 @@ EXPORT_SYMBOL(iwl_tt_initialize);
 /* cleanup thermal throttling management related memory and timer */
 void iwl_tt_exit(struct iwl_priv *priv)
 {
-	struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 
 	/* stop ct_kill_exit_tm timer if activated */
-	del_timer_sync(&priv->power_data.ct_kill_exit_tm);
+	del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
 	cancel_work_sync(&priv->tt_work);
 	cancel_work_sync(&priv->ct_enter);
 	cancel_work_sync(&priv->ct_exit);
 
-	if (priv->power_data.adv_tt) {
+	if (priv->thermal_throttle.advanced_tt) {
 		/* free advance thermal throttling memory */
 		kfree(tt->restriction);
 		tt->restriction = NULL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index 3d49b7a..15e3eab 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -37,13 +37,11 @@ struct iwl_priv;
 #define IWL_ABSOLUTE_MAX		0xFFFFFFFF
 #define IWL_TT_INCREASE_MARGIN	5
 
-/* Tx/Rx restrictions */
-#define IWL_TX_MULTI		0x02
-#define IWL_TX_SINGLE		0x01
-#define IWL_TX_NONE		0x00
-#define IWL_RX_MULTI		0x02
-#define IWL_RX_SINGLE		0x01
-#define IWL_RX_NONE		0x00
+enum iwl_antenna_ok {
+	IWL_ANT_OK_NONE,
+	IWL_ANT_OK_SINGLE,
+	IWL_ANT_OK_MULTI,
+};
 
 /* Thermal Throttling State Machine states */
 enum  iwl_tt_state {
@@ -55,27 +53,30 @@ enum  iwl_tt_state {
 };
 
 /**
- * struct iwl_tt_restriction - Thermal Throttling restriction table used
- *		by advance thermal throttling management
- *		based on the current thermal throttling state, determine
- *		number of tx/rx streams; and the status of HT operation
+ * struct iwl_tt_restriction - Thermal Throttling restriction table
  * @tx_stream: number of tx stream allowed
  * @is_ht: ht enable/disable
  * @rx_stream: number of rx stream allowed
+ *
+ * This table is used by advance thermal throttling management
+ * based on the current thermal throttling state, and determines
+ * the number of tx/rx streams and the status of HT operation.
  */
 struct iwl_tt_restriction {
-	u8 tx_stream;
+	enum iwl_antenna_ok tx_stream;
+	enum iwl_antenna_ok rx_stream;
 	bool is_ht;
-	u8 rx_stream;
 };
 
 /**
- * struct iwl_tt_trans - Thermal Throttling transaction table; used by
- * 		advance thermal throttling algorithm to determine next
- *		thermal state to go based on the current temperature
+ * struct iwl_tt_trans - Thermal Throttling transaction table
  * @next_state:  next thermal throttling mode
  * @tt_low: low temperature threshold to change state
  * @tt_high: high temperature threshold to change state
+ *
+ * This is used by the advanced thermal throttling algorithm
+ * to determine the next thermal state to go based on the
+ * current temperature.
  */
 struct iwl_tt_trans {
 	enum iwl_tt_state next_state;
@@ -85,6 +86,7 @@ struct iwl_tt_trans {
 
 /**
  * struct iwl_tt_mgnt - Thermal Throttling Management structure
+ * @advanced_tt:    advanced thermal throttle required
  * @state:          current Thermal Throttling state
  * @tt_power_mode:  Thermal Throttling power mode index
  *		    being used to set power level when
@@ -99,16 +101,21 @@ struct iwl_tt_trans {
  *		    should be used in tt state; and can HT be enabled or not
  * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling
  *		    state transaction
+ * @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature
+ * @ct_kill_exit_tm: timer to exit thermal kill
  */
 struct iwl_tt_mgmt {
 	enum iwl_tt_state state;
+	bool advanced_tt;
 	u8 tt_power_mode;
 	u8 sys_power_mode;
+	bool ct_kill_toggle;
 #ifdef CONFIG_IWLWIFI_DEBUG
 	s32 tt_previous_temp;
 #endif
 	struct iwl_tt_restriction *restriction;
 	struct iwl_tt_trans *transaction;
+	struct timer_list ct_kill_exit_tm;
 };
 
 enum {
@@ -137,20 +144,13 @@ struct iwl_power_mgr {
 	u8 power_mode;
 	u8 user_power_setting; /* set by user through sysfs */
 	u8 power_disabled; /* set by mac80211's CONF_PS */
-	struct iwl_tt_mgmt tt; /* Thermal Throttling Management */
-	bool adv_tt;		/* false: legacy mode */
-				/* true: advance mode */
-	bool ct_kill_toggle;   /* use to toggle the CSR bit when
-				* checking uCode temperature
-				*/
-	struct timer_list ct_kill_exit_tm;
 };
 
 int iwl_power_update_mode(struct iwl_priv *priv, bool force);
 int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode);
 bool iwl_ht_enabled(struct iwl_priv *priv);
-u8 iwl_tx_ant_restriction(struct iwl_priv *priv);
-u8 iwl_rx_ant_restriction(struct iwl_priv *priv);
+enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv);
+enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv);
 void iwl_tt_enter_ct_kill(struct iwl_priv *priv);
 void iwl_tt_exit_ct_kill(struct iwl_priv *priv);
 void iwl_tt_handler(struct iwl_priv *priv);
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 13/16] iwlwifi: fix missing EXPORT_SYMBOL
  2009-08-07 22:41 [PATCH 0/16] iwlwifi driver updates 07/08/2009 Reinette Chatre
                   ` (11 preceding siblings ...)
  2009-08-07 22:41 ` [PATCH 12/16] iwlwifi: refactor some thermal throttle code Reinette Chatre
@ 2009-08-07 22:41 ` Reinette Chatre
  2009-08-07 22:41 ` [PATCH 14/16] iwlwifi: display correct critical temperature infomation Reinette Chatre
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Reinette Chatre

From: Reinette Chatre <reinette.chatre@intel.com>

When compiling without CONFIG_IWLWIFI_DEBUGFS there is a missing
iwl_update_stats symbol. This is fixed by making this function an inline in
the case when CONFIG_IWLWIFI_DEBUGFS is not set due to the hot path in
which it is used.

Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-core.c |   16 ----------------
 drivers/net/wireless/iwlwifi/iwl-core.h |   19 +++++++++++++++++--
 2 files changed, 17 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 22961e9..44d01a2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -3172,22 +3172,6 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
 	}
 }
 EXPORT_SYMBOL(iwl_update_stats);
-
-#else
-void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
-{
-	struct traffic_stats	*stats;
-
-	if (is_tx)
-		stats = &priv->tx_stats;
-	else
-		stats = &priv->rx_stats;
-
-	if (ieee80211_is_data(fc)) {
-		/* data */
-		stats->data_bytes += len;
-	}
-}
 #endif
 
 #ifdef CONFIG_PM
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index ea8748d..32750f4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -314,6 +314,8 @@ const char *get_mgmt_string(int cmd);
 const char *get_ctrl_string(int cmd);
 void iwl_clear_tx_stats(struct iwl_priv *priv);
 void iwl_clear_rx_stats(struct iwl_priv *priv);
+void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc,
+		      u16 len);
 #else
 static inline int iwl_alloc_traffic_mem(struct iwl_priv *priv)
 {
@@ -333,9 +335,22 @@ static inline void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
 		      u16 length, struct ieee80211_hdr *header)
 {
 }
+static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx,
+				    __le16 fc, u16 len)
+{
+	struct traffic_stats	*stats;
+
+	if (is_tx)
+		stats = &priv->tx_stats;
+	else
+		stats = &priv->rx_stats;
+
+	if (ieee80211_is_data(fc)) {
+		/* data */
+		stats->data_bytes += len;
+	}
+}
 #endif
-void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc,
-		      u16 len);
 /*****************************************************
  * RX handlers.
  * **************************************************/
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 14/16] iwlwifi: display correct critical temperature infomation
  2009-08-07 22:41 [PATCH 0/16] iwlwifi driver updates 07/08/2009 Reinette Chatre
                   ` (12 preceding siblings ...)
  2009-08-07 22:41 ` [PATCH 13/16] iwlwifi: fix missing EXPORT_SYMBOL Reinette Chatre
@ 2009-08-07 22:41 ` Reinette Chatre
  2009-08-07 22:41 ` [PATCH 15/16] iwlwifi: automatically adjust sleep level Reinette Chatre
  2009-08-07 22:41 ` [PATCH 16/16] iwlwifi: disable powersave mode Reinette Chatre
  15 siblings, 0 replies; 22+ messages in thread
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

Do not send CT KILL config command twice and correct critical
temperature informatiom in dmesg

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-core.c |   24 ++++++++++++++++--------
 1 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 44d01a2..36c6e16 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -2227,6 +2227,15 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv)
 
 		ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
 				       sizeof(adv_cmd), &adv_cmd);
+		if (ret)
+			IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
+		else
+			IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
+					"succeeded, "
+					"critical temperature enter is %d,"
+					"exit is %d\n",
+				       priv->hw_params.ct_kill_threshold,
+				       priv->hw_params.ct_kill_exit_threshold);
 		break;
 	default:
 		cmd.critical_temperature_R =
@@ -2234,16 +2243,15 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv)
 
 		ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
 				       sizeof(cmd), &cmd);
+		if (ret)
+			IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
+		else
+			IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
+					"succeeded, "
+					"critical temperature is %d\n",
+					priv->hw_params.ct_kill_threshold);
 		break;
 	}
-	ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
-			       sizeof(cmd), &cmd);
-	if (ret)
-		IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
-	else
-		IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD succeeded, "
-			"critical temperature is %d\n",
-			cmd.critical_temperature_R);
 }
 EXPORT_SYMBOL(iwl_rf_kill_ct_config);
 
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 15/16] iwlwifi: automatically adjust sleep level
  2009-08-07 22:41 [PATCH 0/16] iwlwifi driver updates 07/08/2009 Reinette Chatre
                   ` (13 preceding siblings ...)
  2009-08-07 22:41 ` [PATCH 14/16] iwlwifi: display correct critical temperature infomation Reinette Chatre
@ 2009-08-07 22:41 ` Reinette Chatre
  2009-08-07 22:41 ` [PATCH 16/16] iwlwifi: disable powersave mode Reinette Chatre
  15 siblings, 0 replies; 22+ messages in thread
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Reinette Chatre

From: Johannes Berg <johannes@sipsolutions.net>

Depending on required latency requested by pm_qos (via mac80211)
we can automatically adjust the sleep state. Also, mac80211 has
a user-visible dynamic sleep feature where we are supposed to
stay awake after sending/receiving frames to better receive
response frames to our packets, this can be integrated into the
sleep command.

Currently, and this patch doesn't change that yet, we default
to using sleep level 1 if PS is enabled. With a module parameter
to iwlcore, automatic adjustment to changing network latency
requirements can be enabled -- this isn't yet the default due
to requiring more testing.

The goal is to enable automatic adjustment and then go into the
deepest possible sleep state possible depending on the networking
latency requirements.

This patch does, however, enable IEEE80211_HW_SUPPORTS_DYNAMIC_PS
to avoid the double-timer (one in software and one in the device)
when transmitting -- the exact timeout may be ignored but that is
not of big concern.

Note also that we keep the hard-coded power indices around for
thermal throttling -- the specification of that calls for using
the specified power levels. Those can also be selected in debugfs
to allow easier testing of such parameters.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn.c      |   46 +----
 drivers/net/wireless/iwlwifi/iwl-calib.c    |    2 +-
 drivers/net/wireless/iwlwifi/iwl-commands.h |    7 +
 drivers/net/wireless/iwlwifi/iwl-core.c     |   15 +-
 drivers/net/wireless/iwlwifi/iwl-debug.h    |    2 +
 drivers/net/wireless/iwlwifi/iwl-debugfs.c  |   83 +++++++
 drivers/net/wireless/iwlwifi/iwl-dev.h      |    1 -
 drivers/net/wireless/iwlwifi/iwl-power.c    |  317 +++++++++++++--------------
 drivers/net/wireless/iwlwifi/iwl-power.h    |   30 +--
 drivers/net/wireless/iwlwifi/iwl3945-base.c |   66 +------
 10 files changed, 256 insertions(+), 313 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 319df4a..2232b17 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1606,7 +1606,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
 	set_bit(STATUS_READY, &priv->status);
 	wake_up_interruptible(&priv->wait_command_queue);
 
-	iwl_power_update_mode(priv, 1);
+	iwl_power_update_mode(priv, true);
 
 	/* reassociate for ADHOC mode */
 	if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) {
@@ -2075,7 +2075,7 @@ void iwl_post_associate(struct iwl_priv *priv)
 	 * If chain noise has already been run, then we need to enable
 	 * power management here */
 	if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
-		iwl_power_update_mode(priv, 0);
+		iwl_power_update_mode(priv, false);
 
 	/* Enable Rx differential gain and sensitivity calibrations */
 	iwl_chain_noise_reset(priv);
@@ -2565,47 +2565,6 @@ static ssize_t store_filter_flags(struct device *d,
 static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
 		   store_filter_flags);
 
-static ssize_t store_power_level(struct device *d,
-				 struct device_attribute *attr,
-				 const char *buf, size_t count)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	int ret;
-	unsigned long mode;
-
-
-	mutex_lock(&priv->mutex);
-
-	ret = strict_strtoul(buf, 10, &mode);
-	if (ret)
-		goto out;
-
-	ret = iwl_power_set_user_mode(priv, mode);
-	if (ret) {
-		IWL_DEBUG_MAC80211(priv, "failed setting power mode.\n");
-		goto out;
-	}
-	ret = count;
-
- out:
-	mutex_unlock(&priv->mutex);
-	return ret;
-}
-
-static ssize_t show_power_level(struct device *d,
-				struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	int level = priv->power_data.power_mode;
-	char *p = buf;
-
-	p += sprintf(p, "%d\n", level);
-	return p - buf + 1;
-}
-
-static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
-		   store_power_level);
-
 
 static ssize_t show_statistics(struct device *d,
 			       struct device_attribute *attr, char *buf)
@@ -2698,7 +2657,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
 static struct attribute *iwl_sysfs_entries[] = {
 	&dev_attr_flags.attr,
 	&dev_attr_filter_flags.attr,
-	&dev_attr_power_level.attr,
 	&dev_attr_statistics.attr,
 	&dev_attr_temperature.attr,
 	&dev_attr_tx_power.attr,
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c
index 13180d6..c4b565a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.c
@@ -852,7 +852,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
 		priv->cfg->ops->lib->update_chain_flags(priv);
 
 	data->state = IWL_CHAIN_NOISE_DONE;
-	iwl_power_update_mode(priv, 0);
+	iwl_power_update_mode(priv, false);
 }
 EXPORT_SYMBOL(iwl_chain_noise_calibration);
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 6188c54..68d7719 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -2313,15 +2313,22 @@ struct iwl_spectrum_notification {
  * PM allow:
  *   bit 0 - '0' Driver not allow power management
  *           '1' Driver allow PM (use rest of parameters)
+ *
  * uCode send sleep notifications:
  *   bit 1 - '0' Don't send sleep notification
  *           '1' send sleep notification (SEND_PM_NOTIFICATION)
+ *
  * Sleep over DTIM
  *   bit 2 - '0' PM have to walk up every DTIM
  *           '1' PM could sleep over DTIM till listen Interval.
+ *
  * PCI power managed
  *   bit 3 - '0' (PCI_CFG_LINK_CTRL & 0x1)
  *           '1' !(PCI_CFG_LINK_CTRL & 0x1)
+ *
+ * Fast PD
+ *   bit 4 - '1' Put radio to sleep when receiving frame for others
+ *
  * Force sleep Modes
  *   bit 31/30- '00' use both mac/xtal sleeps
  *              '01' force Mac sleep
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 36c6e16..af73512 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1568,7 +1568,8 @@ int iwl_setup_mac(struct iwl_priv *priv)
 		    IEEE80211_HW_NOISE_DBM |
 		    IEEE80211_HW_AMPDU_AGGREGATION |
 		    IEEE80211_HW_SPECTRUM_MGMT |
-		    IEEE80211_HW_SUPPORTS_PS;
+		    IEEE80211_HW_SUPPORTS_PS |
+		    IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
 	hw->wiphy->interface_modes =
 		BIT(NL80211_IFTYPE_STATION) |
 		BIT(NL80211_IFTYPE_ADHOC);
@@ -1663,8 +1664,6 @@ int iwl_init_drv(struct iwl_priv *priv)
 	priv->qos_data.qos_cap.val = 0;
 
 	priv->rates_mask = IWL_RATES_MASK;
-	/* If power management is turned on, default to CAM mode */
-	priv->power_mode = IWL_POWER_MODE_CAM;
 	priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MAX;
 
 	ret = iwl_init_channel_map(priv);
@@ -2551,7 +2550,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
 		if (bss_conf->assoc) {
 			priv->assoc_id = bss_conf->aid;
 			priv->beacon_int = bss_conf->beacon_int;
-			priv->power_data.dtim_period = bss_conf->dtim_period;
 			priv->timestamp = bss_conf->timestamp;
 			priv->assoc_capability = bss_conf->assoc_capability;
 
@@ -2801,13 +2799,10 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
 		iwl_set_rate(priv);
 	}
 
-	if (changed & IEEE80211_CONF_CHANGE_PS &&
-	    priv->iw_mode == NL80211_IFTYPE_STATION) {
-		priv->power_data.power_disabled =
-			!(conf->flags & IEEE80211_CONF_PS);
-		ret = iwl_power_update_mode(priv, 0);
+	if (changed & IEEE80211_CONF_CHANGE_PS) {
+		ret = iwl_power_update_mode(priv, false);
 		if (ret)
-			IWL_DEBUG_MAC80211(priv, "Error setting power level\n");
+			IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
 	}
 
 	if (changed & IEEE80211_CONF_CHANGE_POWER) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 82befb7..723f38a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -88,6 +88,8 @@ struct iwl_debugfs {
 		struct dentry *file_led;
 #endif
 		struct dentry *file_disable_ht40;
+		struct dentry *file_sleep_level_override;
+		struct dentry *file_current_sleep_command;
 	} dbgfs_data_files;
 	struct dir_rf_files {
 		struct dentry *file_disable_sensitivity;
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 7b578d4..f68fb47 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -776,6 +776,83 @@ static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
 	return ret;
 }
 
+static ssize_t iwl_dbgfs_sleep_level_override_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 value;
+
+	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", &value) != 1)
+		return -EINVAL;
+
+	/*
+	 * Our users expect 0 to be "CAM", but 0 isn't actually
+	 * valid here. However, let's not confuse them and present
+	 * IWL_POWER_INDEX_1 as "1", not "0".
+	 */
+	if (value > 0)
+		value -= 1;
+
+	if (value != -1 && (value < 0 || value >= IWL_POWER_NUM))
+		return -EINVAL;
+
+	priv->power_data.debug_sleep_level_override = value;
+
+	iwl_power_update_mode(priv, false);
+
+	return count;
+}
+
+static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file,
+						   char __user *user_buf,
+						   size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+	char buf[10];
+	int pos, value;
+	const size_t bufsz = sizeof(buf);
+
+	/* see the write function */
+	value = priv->power_data.debug_sleep_level_override;
+	if (value >= 0)
+		value += 1;
+
+	pos = scnprintf(buf, bufsz, "%d\n", value);
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file,
+						    char __user *user_buf,
+						    size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+	char buf[200];
+	int pos = 0, i;
+	const size_t bufsz = sizeof(buf);
+	struct iwl_powertable_cmd *cmd = &priv->power_data.sleep_cmd;
+
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "flags: %#.2x\n", le16_to_cpu(cmd->flags));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "RX/TX timeout: %d/%d usec\n",
+			 le32_to_cpu(cmd->rx_data_timeout),
+			 le32_to_cpu(cmd->tx_data_timeout));
+	for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
+		pos += scnprintf(buf + pos, bufsz - pos,
+				 "sleep_interval[%d]: %d\n", i,
+				 le32_to_cpu(cmd->sleep_interval[i]));
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
 DEBUGFS_READ_WRITE_FILE_OPS(sram);
 DEBUGFS_WRITE_FILE_OPS(log_event);
 DEBUGFS_READ_FILE_OPS(nvm);
@@ -789,6 +866,8 @@ DEBUGFS_READ_FILE_OPS(led);
 #endif
 DEBUGFS_READ_FILE_OPS(thermal_throttling);
 DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
+DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
+DEBUGFS_READ_FILE_OPS(current_sleep_command);
 
 static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
 					 char __user *user_buf,
@@ -1533,6 +1612,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
 #ifdef CONFIG_IWLWIFI_LEDS
 	DEBUGFS_ADD_FILE(led, data);
 #endif
+	DEBUGFS_ADD_FILE(sleep_level_override, data);
+	DEBUGFS_ADD_FILE(current_sleep_command, data);
 	DEBUGFS_ADD_FILE(thermal_throttling, data);
 	DEBUGFS_ADD_FILE(disable_ht40, data);
 	DEBUGFS_ADD_FILE(rx_statistics, debug);
@@ -1572,6 +1653,8 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
 	if (!priv->dbgfs)
 		return;
 
+	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sleep_level_override);
+	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_current_sleep_command);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 1aa2ae6..b96c3c9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1119,7 +1119,6 @@ struct iwl_priv {
 	/* context information */
 	u16 rates_mask;
 
-	u32 power_mode;
 	u8 bssid[ETH_ALEN];
 	u16 rts_threshold;
 	u8 mac_addr[ETH_ALEN];
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 27ad59d..0b16841 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -42,20 +42,35 @@
 #include "iwl-power.h"
 
 /*
- * Setting power level allow the card to go to sleep when not busy.
+ * Setting power level allows the card to go to sleep when not busy.
  *
- * The power level is set to INDEX_1 (the least deep state) by
- * default, and will, in the future, be the deepest state unless
- * otherwise required by pm_qos network latency requirements.
- *
- * Using INDEX_1 without pm_qos is ok because mac80211 will disable
- * PS when even checking every beacon for the TIM bit would exceed
- * the required latency.
+ * We calculate a sleep command based on the required latency, which
+ * we get from mac80211. In order to handle thermal throttling, we can
+ * also use pre-defined power levels.
  */
 
-#define IWL_POWER_RANGE_0_MAX  (2)
-#define IWL_POWER_RANGE_1_MAX  (10)
+/*
+ * For now, keep using power level 1 instead of automatically
+ * adjusting ...
+ */
+bool no_sleep_autoadjust = true;
+module_param(no_sleep_autoadjust, bool, S_IRUGO);
+MODULE_PARM_DESC(no_sleep_autoadjust,
+		 "don't automatically adjust sleep level "
+		 "according to maximum network latency");
 
+/*
+ * This defines the old power levels. They are still used by default
+ * (level 1) and for thermal throttle (levels 3 through 5)
+ */
+
+struct iwl_power_vec_entry {
+	struct iwl_powertable_cmd cmd;
+	u8 no_dtim;
+};
+
+#define IWL_DTIM_RANGE_0_MAX	2
+#define IWL_DTIM_RANGE_1_MAX	10
 
 #define NOSLP cpu_to_le16(0), 0, 0
 #define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
@@ -67,9 +82,8 @@
 				     cpu_to_le32(X3), \
 				     cpu_to_le32(X4)}
 /* default power management (not Tx power) table values */
-/* for DTIM period 0 through IWL_POWER_RANGE_0_MAX */
+/* for DTIM period 0 through IWL_DTIM_RANGE_0_MAX */
 static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
-	{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
 	{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
 	{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
 	{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0},
@@ -78,9 +92,8 @@ static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
 };
 
 
-/* for DTIM period IWL_POWER_RANGE_0_MAX + 1 through IWL_POWER_RANGE_1_MAX */
+/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */
 static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
-	{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
 	{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
 	{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0},
 	{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0},
@@ -88,9 +101,8 @@ static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
 	{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2}
 };
 
-/* for DTIM period > IWL_POWER_RANGE_1_MAX */
+/* for DTIM period > IWL_DTIM_RANGE_1_MAX */
 static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
-	{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
 	{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
 	{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
 	{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
@@ -98,6 +110,56 @@ static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
 	{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
 };
 
+static void iwl_static_sleep_cmd(struct iwl_priv *priv,
+				 struct iwl_powertable_cmd *cmd,
+				 enum iwl_power_level lvl, int period)
+{
+	const struct iwl_power_vec_entry *table;
+	int max_sleep, i;
+	bool skip;
+
+	table = range_2;
+	if (period < IWL_DTIM_RANGE_1_MAX)
+		table = range_1;
+	if (period < IWL_DTIM_RANGE_0_MAX)
+		table = range_0;
+
+	BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM);
+
+	*cmd = table[lvl].cmd;
+
+	if (period == 0) {
+		skip = false;
+		period = 1;
+	} else {
+		skip = !!table[lvl].no_dtim;
+	}
+
+	if (skip) {
+		__le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1];
+		max_sleep = le32_to_cpu(slp_itrvl);
+		if (max_sleep == 0xFF)
+			max_sleep = period * (skip + 1);
+		else if (max_sleep > period)
+			max_sleep = (le32_to_cpu(slp_itrvl) / period) * period;
+		cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
+	} else {
+		max_sleep = period;
+		cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
+	}
+
+	for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
+		if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep)
+			cmd->sleep_interval[i] = cpu_to_le32(max_sleep);
+
+	if (priv->power_data.pci_pm)
+		cmd->flags |= IWL_POWER_PCI_PM_MSK;
+	else
+		cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
+
+	IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1);
+}
+
 /* default Thermal Throttling transaction table
  * Current state   |         Throttling Down               |  Throttling Up
  *=============================================================================
@@ -138,98 +200,44 @@ static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = {
 	{IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false }
 };
 
-/* set card power command */
-static int iwl_set_power(struct iwl_priv *priv, void *cmd)
-{
-	return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
-				sizeof(struct iwl_powertable_cmd), cmd);
-}
 
-/* initialize to default */
-static void iwl_power_init_handle(struct iwl_priv *priv)
+static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv,
+				    struct iwl_powertable_cmd *cmd)
 {
-	struct iwl_power_mgr *pow_data;
-	int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_NUM;
-	struct iwl_powertable_cmd *cmd;
-	int i;
-	u16 lctl;
-
-	IWL_DEBUG_POWER(priv, "Initialize power \n");
-
-	pow_data = &priv->power_data;
-
-	memset(pow_data, 0, sizeof(*pow_data));
-
-	memcpy(&pow_data->pwr_range_0[0], &range_0[0], size);
-	memcpy(&pow_data->pwr_range_1[0], &range_1[0], size);
-	memcpy(&pow_data->pwr_range_2[0], &range_2[0], size);
-
-	lctl = iwl_pcie_link_ctl(priv);
+	memset(cmd, 0, sizeof(*cmd));
 
-	IWL_DEBUG_POWER(priv, "adjust power command flags\n");
+	if (priv->power_data.pci_pm)
+		cmd->flags |= IWL_POWER_PCI_PM_MSK;
 
-	for (i = 0; i < IWL_POWER_NUM; i++) {
-		cmd = &pow_data->pwr_range_0[i].cmd;
-
-		if (lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN)
-			cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
-		else
-			cmd->flags |= IWL_POWER_PCI_PM_MSK;
-	}
+	IWL_DEBUG_POWER(priv, "Sleep command for CAM\n");
 }
 
-/* adjust power command according to DTIM period and power level*/
-static int iwl_update_power_cmd(struct iwl_priv *priv,
-				struct iwl_powertable_cmd *cmd, u16 mode)
+static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
+				     struct iwl_powertable_cmd *cmd,
+				     int dynps_ms, int wakeup_period)
 {
-	struct iwl_power_vec_entry *range;
-	struct iwl_power_mgr *pow_data;
 	int i;
-	u32 max_sleep = 0;
-	u8 period;
-	bool skip;
 
-	if (mode > IWL_POWER_INDEX_5) {
-		IWL_DEBUG_POWER(priv, "Error invalid power mode \n");
-		return -EINVAL;
-	}
+	memset(cmd, 0, sizeof(*cmd));
 
-	pow_data = &priv->power_data;
+	cmd->flags = IWL_POWER_DRIVER_ALLOW_SLEEP_MSK |
+		     IWL_POWER_FAST_PD; /* no use seeing frames for others */
 
-	if (pow_data->dtim_period <= IWL_POWER_RANGE_0_MAX)
-		range = &pow_data->pwr_range_0[0];
-	else if (pow_data->dtim_period <= IWL_POWER_RANGE_1_MAX)
-		range = &pow_data->pwr_range_1[0];
-	else
-		range = &pow_data->pwr_range_2[0];
+	if (priv->power_data.pci_pm)
+		cmd->flags |= IWL_POWER_PCI_PM_MSK;
 
-	period = pow_data->dtim_period;
-	memcpy(cmd, &range[mode].cmd, sizeof(struct iwl_powertable_cmd));
-
-	if (period == 0) {
-		period = 1;
-		skip = false;
-	} else {
-		skip = !!range[mode].no_dtim;
-	}
-
-	if (skip) {
-		__le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1];
-		max_sleep = le32_to_cpu(slp_itrvl);
-		if (max_sleep == 0xFF)
-			max_sleep = period * (skip + 1);
-		else if (max_sleep >  period)
-			max_sleep = (le32_to_cpu(slp_itrvl) / period) * period;
-		cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
-	} else {
-		max_sleep = period;
-		cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
-	}
+	cmd->rx_data_timeout = cpu_to_le32(1000 * dynps_ms);
+	cmd->tx_data_timeout = cpu_to_le32(1000 * dynps_ms);
 
 	for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
-		if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep)
-			cmd->sleep_interval[i] = cpu_to_le32(max_sleep);
+		cmd->sleep_interval[i] = cpu_to_le32(wakeup_period);
+
+	IWL_DEBUG_POWER(priv, "Automatic sleep command\n");
+}
 
+static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
+{
+	IWL_DEBUG_POWER(priv, "Sending power/sleep command\n");
 	IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags);
 	IWL_DEBUG_POWER(priv, "Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout));
 	IWL_DEBUG_POWER(priv, "Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout));
@@ -240,50 +248,54 @@ static int iwl_update_power_cmd(struct iwl_priv *priv,
 			le32_to_cpu(cmd->sleep_interval[3]),
 			le32_to_cpu(cmd->sleep_interval[4]));
 
-	return 0;
+	return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
+				sizeof(struct iwl_powertable_cmd), cmd);
 }
 
 
-/*
- * compute the final power mode index
- */
 int iwl_power_update_mode(struct iwl_priv *priv, bool force)
 {
-	struct iwl_power_mgr *setting = &(priv->power_data);
 	int ret = 0;
 	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-	u16 uninitialized_var(final_mode);
+	bool enabled = (priv->iw_mode == NL80211_IFTYPE_STATION) &&
+			(priv->hw->conf.flags & IEEE80211_CONF_PS);
 	bool update_chains;
+	struct iwl_powertable_cmd cmd;
+	int dtimper;
 
 	/* Don't update the RX chain when chain noise calibration is running */
 	update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
 			priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
 
-	final_mode = priv->power_data.user_power_setting;
-
-	if (setting->power_disabled)
-		final_mode = IWL_POWER_MODE_CAM;
+	if (priv->vif)
+		dtimper = priv->vif->bss_conf.dtim_period;
+	else
+		dtimper = 1;
+
+	/* TT power setting overwrites everything */
+	if (tt->state >= IWL_TI_1)
+		iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper);
+	else if (!enabled)
+		iwl_power_sleep_cam_cmd(priv, &cmd);
+	else if (priv->power_data.debug_sleep_level_override >= 0)
+		iwl_static_sleep_cmd(priv, &cmd,
+				     priv->power_data.debug_sleep_level_override,
+				     dtimper);
+	else if (no_sleep_autoadjust)
+		iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_1, dtimper);
+	else
+		iwl_power_fill_sleep_cmd(priv, &cmd,
+					 priv->hw->conf.dynamic_ps_timeout,
+					 priv->hw->conf.max_sleep_period);
 
-	if (tt->state >= IWL_TI_1) {
-		/* TT power setting overwrite user & system power setting */
-		final_mode = tt->tt_power_mode;
-	}
 	if (iwl_is_ready_rf(priv) &&
-	    ((setting->power_mode != final_mode) || force)) {
-		struct iwl_powertable_cmd cmd;
-
-		if (final_mode != IWL_POWER_MODE_CAM)
+	    (memcmp(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd)) || force)) {
+		if (cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
 			set_bit(STATUS_POWER_PMI, &priv->status);
 
-		iwl_update_power_cmd(priv, &cmd, final_mode);
-		cmd.keep_alive_beacons = 0;
-
-		if (final_mode == IWL_POWER_INDEX_5)
-			cmd.flags |= IWL_POWER_FAST_PD;
-
 		ret = iwl_set_power(priv, &cmd);
 		if (!ret) {
-			if (final_mode == IWL_POWER_MODE_CAM)
+			if (!(cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
 				clear_bit(STATUS_POWER_PMI, &priv->status);
 
 			if (priv->cfg->ops->lib->update_chain_flags &&
@@ -294,7 +306,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
 					"Cannot update the power, chain noise "
 					"calibration running: %d\n",
 					priv->chain_noise_data.state);
-			setting->power_mode = final_mode;
+			memcpy(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd));
 		} else
 			IWL_ERR(priv, "set power fail, ret = %d", ret);
 	}
@@ -303,18 +315,6 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
 }
 EXPORT_SYMBOL(iwl_power_update_mode);
 
-/* set user_power_setting */
-int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode)
-{
-	if (mode >= IWL_POWER_NUM)
-		return -EINVAL;
-
-	priv->power_data.user_power_setting = mode;
-
-	return iwl_power_update_mode(priv, 0);
-}
-EXPORT_SYMBOL(iwl_power_set_user_mode);
-
 bool iwl_ht_enabled(struct iwl_priv *priv)
 {
 	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
@@ -349,7 +349,6 @@ enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv)
 	restriction = tt->restriction + tt->state;
 	return restriction->rx_stream;
 }
-EXPORT_SYMBOL(iwl_rx_ant_restriction);
 
 #define CT_KILL_EXIT_DURATION (5)	/* 5 seconds duration */
 
@@ -429,7 +428,6 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
 {
 	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 	enum iwl_tt_state old_state;
-	struct iwl_power_mgr *setting = &priv->power_data;
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 	if ((tt->tt_previous_temp) &&
@@ -456,24 +454,13 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
 	tt->tt_previous_temp = temp;
 #endif
 	if (tt->state != old_state) {
-		if (old_state == IWL_TI_0) {
-			tt->sys_power_mode = setting->power_mode;
-			IWL_DEBUG_POWER(priv, "current power mode: %u\n",
-				setting->power_mode);
-		}
 		switch (tt->state) {
 		case IWL_TI_0:
-			/* when system ready to go back to IWL_TI_0 state
-			 * using system power mode instead of TT power mode
-			 * revert back to the orginal power mode which was saved
-			 * before enter Thermal Throttling state
-			 * update priv->power_data.user_power_setting to the
-			 * required power mode to make sure
-			 * iwl_power_update_mode() will update power correctly.
+			/*
+			 * When the system is ready to go back to IWL_TI_0
+			 * we only have to call iwl_power_update_mode() to
+			 * do so.
 			 */
-			priv->power_data.user_power_setting =
-				tt->sys_power_mode;
-			tt->tt_power_mode = tt->sys_power_mode;
 			break;
 		case IWL_TI_1:
 			tt->tt_power_mode = IWL_POWER_INDEX_3;
@@ -576,13 +563,8 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
 	}
 	if (changed) {
 		struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
-		struct iwl_power_mgr *setting = &priv->power_data;
 
 		if (tt->state >= IWL_TI_1) {
-			/* if switching from IWL_TI_0 to other TT state
-			 * save previous power setting in tt->sys_power_mode */
-			if (old_state == IWL_TI_0)
-				tt->sys_power_mode = setting->power_mode;
 			/* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */
 			tt->tt_power_mode = IWL_POWER_INDEX_5;
 			if (!iwl_ht_enabled(priv))
@@ -599,17 +581,11 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
 			}
 
 		} else {
-			/* restore system power setting */
-			/* the previous power mode was saved in
-			 * tt->sys_power_mode when system move into
-			 * Thermal Throttling state
-			 * set power_data.user_power_setting to the previous
-			 * system power mode to make sure power will get
-			 * updated correctly
+			/*
+			 * restore system power setting -- it will be
+			 * recalculated automatically.
 			 */
-			priv->power_data.user_power_setting =
-				tt->sys_power_mode;
-			tt->tt_power_mode = tt->sys_power_mode;
+
 			/* check HT capability and set
 			 * according to the system HT capability
 			 * in case get disabled before */
@@ -761,7 +737,6 @@ EXPORT_SYMBOL(iwl_tt_handler);
 void iwl_tt_initialize(struct iwl_priv *priv)
 {
 	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-	struct iwl_power_mgr *setting = &priv->power_data;
 	int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
 	struct iwl_tt_trans *transaction;
 
@@ -770,8 +745,6 @@ void iwl_tt_initialize(struct iwl_priv *priv)
 	memset(tt, 0, sizeof(struct iwl_tt_mgmt));
 
 	tt->state = IWL_TI_0;
-	tt->sys_power_mode = setting->power_mode;
-	tt->tt_power_mode = tt->sys_power_mode;
 	init_timer(&priv->thermal_throttle.ct_kill_exit_tm);
 	priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv;
 	priv->thermal_throttle.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill;
@@ -849,9 +822,13 @@ EXPORT_SYMBOL(iwl_tt_exit);
 /* initialize to default */
 void iwl_power_initialize(struct iwl_priv *priv)
 {
-	iwl_power_init_handle(priv);
-	priv->power_data.user_power_setting = IWL_POWER_INDEX_1;
-	/* default to disabled until mac80211 says otherwise */
-	priv->power_data.power_disabled = 1;
+	u16 lctl = iwl_pcie_link_ctl(priv);
+
+	priv->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+
+	priv->power_data.debug_sleep_level_override = -1;
+
+	memset(&priv->power_data.sleep_cmd, 0,
+		sizeof(priv->power_data.sleep_cmd));
 }
 EXPORT_SYMBOL(iwl_power_initialize);
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index 15e3eab..df6f6a4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -28,11 +28,8 @@
 #ifndef __iwl_power_setting_h__
 #define __iwl_power_setting_h__
 
-#include <net/mac80211.h>
 #include "iwl-commands.h"
 
-struct iwl_priv;
-
 #define IWL_ABSOLUTE_ZERO		0
 #define IWL_ABSOLUTE_MAX		0xFFFFFFFF
 #define IWL_TT_INCREASE_MARGIN	5
@@ -93,8 +90,6 @@ struct iwl_tt_trans {
  * 		    when thermal throttling state != IWL_TI_0
  *		    the tt_power_mode should set to different
  *		    power mode based on the current tt state
- * @sys_power_mode: previous system power mode
- *                  before transition into TT state
  * @tt_previous_temperature: last measured temperature
  * @iwl_tt_restriction: ptr to restriction tbl, used by advance
  *		    thermal throttling to determine how many tx/rx streams
@@ -108,7 +103,6 @@ struct iwl_tt_mgmt {
 	enum iwl_tt_state state;
 	bool advanced_tt;
 	u8 tt_power_mode;
-	u8 sys_power_mode;
 	bool ct_kill_toggle;
 #ifdef CONFIG_IWLWIFI_DEBUG
 	s32 tt_previous_temp;
@@ -118,8 +112,7 @@ struct iwl_tt_mgmt {
 	struct timer_list ct_kill_exit_tm;
 };
 
-enum {
-	IWL_POWER_MODE_CAM, /* Continuously Aware Mode, always on */
+enum iwl_power_level {
 	IWL_POWER_INDEX_1,
 	IWL_POWER_INDEX_2,
 	IWL_POWER_INDEX_3,
@@ -128,26 +121,13 @@ enum {
 	IWL_POWER_NUM
 };
 
-/* Power management (not Tx power) structures */
-
-struct iwl_power_vec_entry {
-	struct iwl_powertable_cmd cmd;
-	u8 no_dtim;
-};
-
 struct iwl_power_mgr {
-	struct iwl_power_vec_entry pwr_range_0[IWL_POWER_NUM];
-	struct iwl_power_vec_entry pwr_range_1[IWL_POWER_NUM];
-	struct iwl_power_vec_entry pwr_range_2[IWL_POWER_NUM];
-	u32 dtim_period;
-	/* final power level that used to calculate final power command */
-	u8 power_mode;
-	u8 user_power_setting; /* set by user through sysfs */
-	u8 power_disabled; /* set by mac80211's CONF_PS */
+	struct iwl_powertable_cmd sleep_cmd;
+	int debug_sleep_level_override;
+	bool pci_pm;
 };
 
 int iwl_power_update_mode(struct iwl_priv *priv, bool force);
-int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode);
 bool iwl_ht_enabled(struct iwl_priv *priv);
 enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv);
 enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv);
@@ -158,4 +138,6 @@ void iwl_tt_initialize(struct iwl_priv *priv);
 void iwl_tt_exit(struct iwl_priv *priv);
 void iwl_power_initialize(struct iwl_priv *priv);
 
+extern bool no_sleep_autoadjust;
+
 #endif  /* __iwl_power_setting_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index e5fa672..e617411 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -3554,65 +3554,6 @@ static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, show_retry_rate,
 		   store_retry_rate);
 
 
-static ssize_t store_power_level(struct device *d,
-				 struct device_attribute *attr,
-				 const char *buf, size_t count)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	int ret;
-	unsigned long mode;
-
-
-	mutex_lock(&priv->mutex);
-
-	ret = strict_strtoul(buf, 10, &mode);
-	if (ret)
-		goto out;
-
-	ret = iwl_power_set_user_mode(priv, mode);
-	if (ret) {
-		IWL_DEBUG_MAC80211(priv, "failed setting power mode.\n");
-		goto out;
-	}
-	ret = count;
-
- out:
-	mutex_unlock(&priv->mutex);
-	return ret;
-}
-
-static ssize_t show_power_level(struct device *d,
-				struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	int level = priv->power_data.power_mode;
-	char *p = buf;
-
-	p += sprintf(p, "%d\n", level);
-	return p - buf + 1;
-}
-
-static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR,
-		   show_power_level, store_power_level);
-
-#define MAX_WX_STRING 80
-
-/* Values are in microsecond */
-static const s32 timeout_duration[] = {
-	350000,
-	250000,
-	75000,
-	37000,
-	25000,
-};
-static const s32 period_duration[] = {
-	400000,
-	700000,
-	1000000,
-	1000000,
-	1000000
-};
-
 static ssize_t show_channels(struct device *d,
 			     struct device_attribute *attr, char *buf)
 {
@@ -3789,7 +3730,6 @@ static struct attribute *iwl3945_sysfs_entries[] = {
 #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
 	&dev_attr_measurement.attr,
 #endif
-	&dev_attr_power_level.attr,
 	&dev_attr_retry_rate.attr,
 	&dev_attr_statistics.attr,
 	&dev_attr_status.attr,
@@ -3854,8 +3794,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
 	priv->qos_data.qos_cap.val = 0;
 
 	priv->rates_mask = IWL_RATES_MASK;
-	/* If power management is turned on, default to CAM mode */
-	priv->power_mode = IWL_POWER_MODE_CAM;
 	priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
 
 	if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
@@ -3902,7 +3840,9 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
 	/* Tell mac80211 our characteristics */
 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
 		    IEEE80211_HW_NOISE_DBM |
-		    IEEE80211_HW_SPECTRUM_MGMT;
+		    IEEE80211_HW_SPECTRUM_MGMT |
+		    IEEE80211_HW_SUPPORTS_PS |
+		    IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
 
 	hw->wiphy->interface_modes =
 		BIT(NL80211_IFTYPE_STATION) |
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 16/16] iwlwifi: disable powersave mode
  2009-08-07 22:41 [PATCH 0/16] iwlwifi driver updates 07/08/2009 Reinette Chatre
                   ` (14 preceding siblings ...)
  2009-08-07 22:41 ` [PATCH 15/16] iwlwifi: automatically adjust sleep level Reinette Chatre
@ 2009-08-07 22:41 ` Reinette Chatre
  2009-08-08  8:25   ` Kalle Valo
  15 siblings, 1 reply; 22+ messages in thread
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

The enabling of powersaving had a big impact on reliability and
performance. Throughput on n band suffered especially. With power save
support enabled we see significant ping response times, dropped frames, and
reduced throughput. These are captured in the following bug reports:

http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2051
http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2053

Disable power save by default, add "iwl_support_ps" module parameter
that can be used to enable it again.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-core.c  |    7 ++++---
 drivers/net/wireless/iwlwifi/iwl-power.c |    8 ++++++++
 drivers/net/wireless/iwlwifi/iwl-power.h |    2 +-
 3 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index af73512..90b25b1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1567,9 +1567,10 @@ int iwl_setup_mac(struct iwl_priv *priv)
 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
 		    IEEE80211_HW_NOISE_DBM |
 		    IEEE80211_HW_AMPDU_AGGREGATION |
-		    IEEE80211_HW_SPECTRUM_MGMT |
-		    IEEE80211_HW_SUPPORTS_PS |
-		    IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
+		    IEEE80211_HW_SPECTRUM_MGMT;
+	if (iwl_support_ps)
+		hw->flags |= IEEE80211_HW_SUPPORTS_PS |
+			     IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
 	hw->wiphy->interface_modes =
 		BIT(NL80211_IFTYPE_STATION) |
 		BIT(NL80211_IFTYPE_ADHOC);
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 0b16841..5a7d821 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -1,3 +1,4 @@
+
 /******************************************************************************
  *
  * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved.
@@ -50,6 +51,13 @@
  */
 
 /*
+ * For now, disable power save function
+ */
+bool iwl_support_ps;
+module_param(iwl_support_ps, bool, S_IRUGO);
+MODULE_PARM_DESC(iwl_support_ps,
+		 "power save support (deprecated) (default disabled)");
+/*
  * For now, keep using power level 1 instead of automatically
  * adjusting ...
  */
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index df6f6a4..fb3ce90 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -139,5 +139,5 @@ void iwl_tt_exit(struct iwl_priv *priv);
 void iwl_power_initialize(struct iwl_priv *priv);
 
 extern bool no_sleep_autoadjust;
-
+extern bool iwl_support_ps;
 #endif  /* __iwl_power_setting_h__ */
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH 16/16] iwlwifi: disable powersave mode
  2009-08-07 22:41 ` [PATCH 16/16] iwlwifi: disable powersave mode Reinette Chatre
@ 2009-08-08  8:25   ` Kalle Valo
  2009-08-08 19:36     ` reinette chatre
  0 siblings, 1 reply; 22+ messages in thread
From: Kalle Valo @ 2009-08-08  8:25 UTC (permalink / raw)
  To: Reinette Chatre; +Cc: linville, linux-wireless, ipw3945-devel, Wey-Yi Guy

Reinette Chatre <reinette.chatre@intel.com> writes:

> From: Wey-Yi Guy <wey-yi.w.guy@intel.com>
>
> The enabling of powersaving had a big impact on reliability and
> performance. Throughput on n band suffered especially. With power save
> support enabled we see significant ping response times, dropped frames, and
> reduced throughput. These are captured in the following bug reports:
>
> http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2051
> http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2053
>
> Disable power save by default, add "iwl_support_ps" module parameter
> that can be used to enable it again.

You are again creating driver specific parameters. But we should be
moving away from this and instead use just generic interfaces. Please,
think three times (or even more) whenever creating new driver specific
interfaces, be it module parameters, sysfs files etc.. It's a
maintenance nightmare and also very confusing for the users. We need to
focus on nl80211 and make it work properly with all drivers.

For the problem at hand, I see two options:

1. Users seeing the problem disable power save either via wext or with
   CONFIG_CFG80211_DEFAULT_PS and everyone else still can use power
   save. The issue will be investigated and fixed. If the AP is buggy,
   there isn't much we can do.

2. If you think the problem is widespread, remove
   IEEE80211_HW_SUPPORTS_PS from the driver, fix the issues and renable
   power save support.

-- 
Kalle Valo

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 16/16] iwlwifi: disable powersave mode
  2009-08-08  8:25   ` Kalle Valo
@ 2009-08-08 19:36     ` reinette chatre
  2009-08-12 18:54       ` Kalle Valo
  0 siblings, 1 reply; 22+ messages in thread
From: reinette chatre @ 2009-08-08 19:36 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linville, linux-wireless, ipw3945-devel, Guy, Wey-Yi W

Hi Kalle,

Thank you for looking at our patches. You have great feedback.

On Sat, 2009-08-08 at 01:25 -0700, Kalle Valo wrote:
> Reinette Chatre <reinette.chatre@intel.com> writes:
> 
> > From: Wey-Yi Guy <wey-yi.w.guy@intel.com>
> >
> > The enabling of powersaving had a big impact on reliability and
> > performance. Throughput on n band suffered especially. With power save
> > support enabled we see significant ping response times, dropped frames, and
> > reduced throughput. These are captured in the following bug reports:
> >
> > http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2051
> > http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2053
> >
> > Disable power save by default, add "iwl_support_ps" module parameter
> > that can be used to enable it again.
> 
> You are again creating driver specific parameters. But we should be
> moving away from this and instead use just generic interfaces. Please,
> think three times (or even more) whenever creating new driver specific
> interfaces, be it module parameters, sysfs files etc.. It's a
> maintenance nightmare and also very confusing for the users. We need to
> focus on nl80211 and make it work properly with all drivers.

What we have done here is not intended to be maintained at all - this is
why the module parameter description reads "power save support
(deprecated) (default disabled)" - it is deprecated from the beginning.

> 
> For the problem at hand, I see two options:
> 
> 1. Users seeing the problem disable power save either via wext or with
>    CONFIG_CFG80211_DEFAULT_PS and everyone else still can use power
>    save. The issue will be investigated and fixed. If the AP is buggy,
>    there isn't much we can do.

Please take a look at those bug reports. What we are seeing is huge ping
delays ( > 1000ms rtt), dropped frames which is stalling connections,
and throughput dropping in half. This is too severe to have powersave
enabled at this time.

> 
> 2. If you think the problem is widespread, remove
>    IEEE80211_HW_SUPPORTS_PS from the driver, fix the issues and renable
>    power save support.

Yes - this is the goal of this patch. At the same time we would also
like to make it easier for the people who are testing this issue right
now and having the module parameter makes their life easier.


This module parameter is a temporary measure used to help us fix the
power save issues. When the issues have been resolved we will enable
power save support by default and remove the module parameter.


Reinette




^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 16/16] iwlwifi: disable powersave mode
  2009-08-08 19:36     ` reinette chatre
@ 2009-08-12 18:54       ` Kalle Valo
  2009-08-12 21:53         ` reinette chatre
  0 siblings, 1 reply; 22+ messages in thread
From: Kalle Valo @ 2009-08-12 18:54 UTC (permalink / raw)
  To: reinette chatre; +Cc: linville, linux-wireless, ipw3945-devel, Guy, Wey-Yi W

reinette chatre <reinette.chatre@intel.com> writes:

> Hi Kalle,

Hello,

> Thank you for looking at our patches. You have great feedback.

Thank you for listening :)

>> You are again creating driver specific parameters. But we should be
>> moving away from this and instead use just generic interfaces. Please,
>> think three times (or even more) whenever creating new driver specific
>> interfaces, be it module parameters, sysfs files etc.. It's a
>> maintenance nightmare and also very confusing for the users. We need to
>> focus on nl80211 and make it work properly with all drivers.
>
> What we have done here is not intended to be maintained at all - this is
> why the module parameter description reads "power save support
> (deprecated) (default disabled)" - it is deprecated from the beginning.

Yes, I understand this. But creating a new module parameters should be
added carefully only when really needed, just to avoid confusion within
users. And it sounds wrong to create a new variable which is deprecated
from the beginning. If it needs to be deprecated, don't create it at
all. Simple as that.

What I'm worried is the complexity of the driver interfaces and
configuration methods. For iwlwifi power save, after this patch, we have
now:

o Wireless Extensions
o sysfs
o CONFIG_CFG80211_DEFAULT_PS Kconfig parameter
o module parameter

Just think how confused an average Linux user will be? Instead of adding
more, we should instead decrease the ways to configure power save. sysfs
and the module parameter are high on my list for removal.

>> For the problem at hand, I see two options:
>> 
>> 1. Users seeing the problem disable power save either via wext or with
>>    CONFIG_CFG80211_DEFAULT_PS and everyone else still can use power
>>    save. The issue will be investigated and fixed. If the AP is buggy,
>>    there isn't much we can do.
>
> Please take a look at those bug reports. What we are seeing is huge ping
> delays ( > 1000ms rtt), dropped frames which is stalling connections,
> and throughput dropping in half. This is too severe to have powersave
> enabled at this time.

Yes, that makes sense. Then disable power save from iwlwifi until the
problem is solved (or analysed that it's a problem on AP), but don't
create a new module parameter.

>> 2. If you think the problem is widespread, remove
>>    IEEE80211_HW_SUPPORTS_PS from the driver, fix the issues and renable
>>    power save support.
>
> Yes - this is the goal of this patch. At the same time we would also
> like to make it easier for the people who are testing this issue right
> now and having the module parameter makes their life easier.

The very few users who want to test this can apply a patch or edit the
source code. It's a oneliner anyway.

> This module parameter is a temporary measure used to help us fix the
> power save issues. When the issues have been resolved we will enable
> power save support by default and remove the module parameter.

I'm not going to fight about this, for now, but in the future I hope
that people would consider carefully before adding hacks like this. If
all drivers create their own configuration parameters all the time, in
the end it will become a maintenance nightmare.

-- 
Kalle Valo

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 16/16] iwlwifi: disable powersave mode
  2009-08-12 18:54       ` Kalle Valo
@ 2009-08-12 21:53         ` reinette chatre
  2009-08-14 17:20           ` Kalle Valo
  0 siblings, 1 reply; 22+ messages in thread
From: reinette chatre @ 2009-08-12 21:53 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linville, linux-wireless, ipw3945-devel, Guy, Wey-Yi W

On Wed, 2009-08-12 at 11:54 -0700, Kalle Valo wrote:
> reinette chatre <reinette.chatre@intel.com> writes:

> >> You are again creating driver specific parameters. But we should be
> >> moving away from this and instead use just generic interfaces. Please,
> >> think three times (or even more) whenever creating new driver specific
> >> interfaces, be it module parameters, sysfs files etc.. It's a
> >> maintenance nightmare and also very confusing for the users. We need to
> >> focus on nl80211 and make it work properly with all drivers.
> >
> > What we have done here is not intended to be maintained at all - this is
> > why the module parameter description reads "power save support
> > (deprecated) (default disabled)" - it is deprecated from the beginning.
> 
> Yes, I understand this. But creating a new module parameters should be
> added carefully only when really needed, just to avoid confusion within
> users. And it sounds wrong to create a new variable which is deprecated
> from the beginning. If it needs to be deprecated, don't create it at
> all. Simple as that.
> 
> What I'm worried is the complexity of the driver interfaces and
> configuration methods. For iwlwifi power save, after this patch, we have
> now:
> 
> o Wireless Extensions
> o sysfs
> o CONFIG_CFG80211_DEFAULT_PS Kconfig parameter

We could not see how any of the current measures can be used to
accomplish out goal. Fortunately Johannes implemented something that now
can be used to accomplish this.

John, could you please revert this patch? Johannes's new "cfg80211:
allow driver to override PS default" makes it possible for us to have
power save support disabled.

Thank you very much

Reinette



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 16/16] iwlwifi: disable powersave mode
  2009-08-12 21:53         ` reinette chatre
@ 2009-08-14 17:20           ` Kalle Valo
  0 siblings, 0 replies; 22+ messages in thread
From: Kalle Valo @ 2009-08-14 17:20 UTC (permalink / raw)
  To: reinette chatre; +Cc: linville, linux-wireless, ipw3945-devel, Guy, Wey-Yi W

reinette chatre <reinette.chatre@intel.com> writes:

>> What I'm worried is the complexity of the driver interfaces and
>> configuration methods. For iwlwifi power save, after this patch, we have
>> now:
>> 
>> o Wireless Extensions
>> o sysfs
>> o CONFIG_CFG80211_DEFAULT_PS Kconfig parameter
>
> We could not see how any of the current measures can be used to
> accomplish out goal. Fortunately Johannes implemented something that now
> can be used to accomplish this.

Yes, Johannes' idea is a perfect compromise. Thank you both.

-- 
Kalle Valo

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2009-08-14 17:26 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-08-07 22:41 [PATCH 0/16] iwlwifi driver updates 07/08/2009 Reinette Chatre
2009-08-07 22:41 ` [PATCH 01/16] iwlwifi: re-introduce per device debugging Reinette Chatre
2009-08-07 22:41 ` [PATCH 02/16] iwlwifi: name changed from "fat" to "ht40" Reinette Chatre
2009-08-07 22:41 ` [PATCH 03/16] iwlwifi: new debugging feature for dumping data traffic Reinette Chatre
2009-08-07 22:41 ` [PATCH 04/16] iwlwifi: Traffic type and counter for debugFs Reinette Chatre
2009-08-07 22:41 ` [PATCH 05/16] iwlwifi: tx/rx queue pointer information Reinette Chatre
2009-08-07 22:41 ` [PATCH 06/16] iwlwifi: uCode statistics notification counter Reinette Chatre
2009-08-07 22:41 ` [PATCH 07/16] iwlwifi: Display sensitivity and chain noise information Reinette Chatre
2009-08-07 22:41 ` [PATCH 08/16] iwlwifi: revert uCode Alive notification with timeout Reinette Chatre
2009-08-07 22:41 ` [PATCH 09/16] iwlwifi: fix thermal throttling locking problem Reinette Chatre
2009-08-07 22:41 ` [PATCH 10/16] iwlwifi: fix legacy thermal throttling power index Reinette Chatre
2009-08-07 22:41 ` [PATCH 11/16] iwlwifi: handle the case when set power fail Reinette Chatre
2009-08-07 22:41 ` [PATCH 12/16] iwlwifi: refactor some thermal throttle code Reinette Chatre
2009-08-07 22:41 ` [PATCH 13/16] iwlwifi: fix missing EXPORT_SYMBOL Reinette Chatre
2009-08-07 22:41 ` [PATCH 14/16] iwlwifi: display correct critical temperature infomation Reinette Chatre
2009-08-07 22:41 ` [PATCH 15/16] iwlwifi: automatically adjust sleep level Reinette Chatre
2009-08-07 22:41 ` [PATCH 16/16] iwlwifi: disable powersave mode Reinette Chatre
2009-08-08  8:25   ` Kalle Valo
2009-08-08 19:36     ` reinette chatre
2009-08-12 18:54       ` Kalle Valo
2009-08-12 21:53         ` reinette chatre
2009-08-14 17:20           ` Kalle Valo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).