* Mesh fixes and improvements
From: Javier Cardona @ 2009-08-08 3:38 UTC (permalink / raw)
To: linux-wireless; +Cc: andrey, johannes, linville, devel
[Resent with proper patch numbering...]
This series includes some fixes, testing aids and improvements to the mesh
stack. It is important to note that the patch
"Use-3-address-format-for-mesh-broadcast-frames" breaks compatibility with
previous versions. This is unavoidable and will keep happening as new versions
of the 802.11s drafts are produced.
Also, I'm not sure if "Simulate-transmission-losses-on-plinks-to-..." should be
merged upstream, but we find it really useful to test mesh configurations.
Please comment if you have different opinions on its adequacy or
implementation.
Cheers,
Javier
^ permalink raw reply
* [PATCH] mac80211: Moved mpath and mpp growth to mesh workqueue.
From: Javier Cardona @ 2009-08-08 3:31 UTC (permalink / raw)
To: linux-wireless; +Cc: Javier Cardona, andrey, johannes, linville, devel
In-Reply-To: <1249702314-32504-8-git-send-email-javier@cozybit.com>
This prevents calling rcu_synchronize from within the tx path.
Also, re-enable mesh in Kconfig
Signed-off-by: Javier Cardona <javier@cozybit.com>
---
net/mac80211/Kconfig | 1 -
net/mac80211/ieee80211_i.h | 2 +-
net/mac80211/mesh.c | 75 +++-------------------
net/mac80211/mesh.h | 20 ++++++-
net/mac80211/mesh_pathtbl.c | 146 ++++++++++++++++++++++++++++++++-----------
5 files changed, 139 insertions(+), 105 deletions(-)
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 7dd77b6..9b4fcbc 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -66,7 +66,6 @@ endmenu
config MAC80211_MESH
bool "Enable mac80211 mesh networking (pre-802.11s) support"
depends on MAC80211 && EXPERIMENTAL
- depends on BROKEN
---help---
This options enables support of Draft 802.11s mesh networking.
The implementation is based on Draft 1.08 of the Mesh Networking
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d6bd7dd..a6abc7d 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -355,7 +355,7 @@ struct ieee80211_if_mesh {
unsigned long timers_running;
- bool housekeeping;
+ unsigned long wrkq_flags;
u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
size_t mesh_id_len;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 3b49d39..619364c 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -47,7 +47,7 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- ifmsh->housekeeping = true;
+ ifmsh->wrkq_flags |= MESH_WORK_HOUSEKEEPING;
if (local->quiescing) {
set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
@@ -320,30 +320,6 @@ struct mesh_table *mesh_table_alloc(int size_order)
return newtbl;
}
-static void __mesh_table_free(struct mesh_table *tbl)
-{
- kfree(tbl->hash_buckets);
- kfree(tbl->hashwlock);
- kfree(tbl);
-}
-
-void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
-{
- struct hlist_head *mesh_hash;
- struct hlist_node *p, *q;
- int i;
-
- mesh_hash = tbl->hash_buckets;
- for (i = 0; i <= tbl->hash_mask; i++) {
- spin_lock(&tbl->hashwlock[i]);
- hlist_for_each_safe(p, q, &mesh_hash[i]) {
- tbl->free_node(p, free_leafs);
- atomic_dec(&tbl->entries);
- }
- spin_unlock(&tbl->hashwlock[i]);
- }
- __mesh_table_free(tbl);
-}
static void ieee80211_mesh_path_timer(unsigned long data)
{
@@ -360,44 +336,6 @@ static void ieee80211_mesh_path_timer(unsigned long data)
ieee80211_queue_work(&local->hw, &ifmsh->work);
}
-struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
-{
- struct mesh_table *newtbl;
- struct hlist_head *oldhash;
- struct hlist_node *p, *q;
- int i;
-
- if (atomic_read(&tbl->entries)
- < tbl->mean_chain_len * (tbl->hash_mask + 1))
- goto endgrow;
-
- newtbl = mesh_table_alloc(tbl->size_order + 1);
- if (!newtbl)
- goto endgrow;
-
- newtbl->free_node = tbl->free_node;
- newtbl->mean_chain_len = tbl->mean_chain_len;
- newtbl->copy_node = tbl->copy_node;
- atomic_set(&newtbl->entries, atomic_read(&tbl->entries));
-
- oldhash = tbl->hash_buckets;
- for (i = 0; i <= tbl->hash_mask; i++)
- hlist_for_each(p, &oldhash[i])
- if (tbl->copy_node(p, newtbl) < 0)
- goto errcopy;
-
- return newtbl;
-
-errcopy:
- for (i = 0; i <= newtbl->hash_mask; i++) {
- hlist_for_each_safe(p, q, &newtbl->hash_buckets[i])
- tbl->free_node(p, 0);
- }
- __mesh_table_free(newtbl);
-endgrow:
- return NULL;
-}
-
/**
* ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame
* @hdr: 802.11 frame header
@@ -487,7 +425,6 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
if (free_plinks != sdata->u.mesh.accepting_plinks)
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
- ifmsh->housekeeping = false;
mod_timer(&ifmsh->housekeeping_timer,
round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
}
@@ -524,7 +461,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_local *local = sdata->local;
- ifmsh->housekeeping = true;
+ ifmsh->wrkq_flags |= MESH_WORK_HOUSEKEEPING;
queue_work(local->hw, &ifmsh->work);
sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
@@ -664,7 +601,13 @@ static void ieee80211_mesh_work(struct work_struct *work)
ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval)))
mesh_path_start_discovery(sdata);
- if (ifmsh->housekeeping)
+ if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags))
+ mesh_mpath_table_grow();
+
+ if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags))
+ mesh_mpp_table_grow();
+
+ if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags))
ieee80211_mesh_housekeeping(sdata, ifmsh);
}
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index b6ea100..fd4031f 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -44,6 +44,23 @@ enum mesh_path_flags {
};
/**
+ * enum mesh_deferred_task_flags - mac80211 mesh deferred tasks
+ *
+ *
+ *
+ * @MESH_WORK_HOUSEKEEPING: run the periodic mesh housekeeping tasks
+ * @MESH_WORK_GROW_MPATH_TABLE: the mesh path table is full and needs
+ * to grow.
+ * @MESH_WORK_GROW_MPP_TABLE: the mesh portals table is full and needs to
+ * grow
+ */
+enum mesh_deferred_task_flags {
+ MESH_WORK_HOUSEKEEPING,
+ MESH_WORK_GROW_MPATH_TABLE,
+ MESH_WORK_GROW_MPP_TABLE,
+};
+
+/**
* struct mesh_path - mac80211 mesh path structure
*
* @dst: mesh path destination mac address
@@ -251,7 +268,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
/* Mesh tables */
struct mesh_table *mesh_table_alloc(int size_order);
void mesh_table_free(struct mesh_table *tbl, bool free_leafs);
-struct mesh_table *mesh_table_grow(struct mesh_table *tbl);
+void mesh_mpath_table_grow(void);
+void mesh_mpp_table_grow(void);
u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata,
struct mesh_table *tbl);
/* Mesh paths */
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 431865a..97e14bc 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -39,6 +39,69 @@ static struct mesh_table *mesh_paths;
static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */
int mesh_paths_generation;
+static void __mesh_table_free(struct mesh_table *tbl)
+{
+ kfree(tbl->hash_buckets);
+ kfree(tbl->hashwlock);
+ kfree(tbl);
+}
+
+void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
+{
+ struct hlist_head *mesh_hash;
+ struct hlist_node *p, *q;
+ int i;
+
+ mesh_hash = tbl->hash_buckets;
+ for (i = 0; i <= tbl->hash_mask; i++) {
+ spin_lock(&tbl->hashwlock[i]);
+ hlist_for_each_safe(p, q, &mesh_hash[i]) {
+ tbl->free_node(p, free_leafs);
+ atomic_dec(&tbl->entries);
+ }
+ spin_unlock(&tbl->hashwlock[i]);
+ }
+ __mesh_table_free(tbl);
+}
+
+static struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
+{
+ struct mesh_table *newtbl;
+ struct hlist_head *oldhash;
+ struct hlist_node *p, *q;
+ int i;
+
+ if (atomic_read(&tbl->entries)
+ < tbl->mean_chain_len * (tbl->hash_mask + 1))
+ goto endgrow;
+
+ newtbl = mesh_table_alloc(tbl->size_order + 1);
+ if (!newtbl)
+ goto endgrow;
+
+ newtbl->free_node = tbl->free_node;
+ newtbl->mean_chain_len = tbl->mean_chain_len;
+ newtbl->copy_node = tbl->copy_node;
+ atomic_set(&newtbl->entries, atomic_read(&tbl->entries));
+
+ oldhash = tbl->hash_buckets;
+ for (i = 0; i <= tbl->hash_mask; i++)
+ hlist_for_each(p, &oldhash[i])
+ if (tbl->copy_node(p, newtbl) < 0)
+ goto errcopy;
+
+ return newtbl;
+
+errcopy:
+ for (i = 0; i <= newtbl->hash_mask; i++) {
+ hlist_for_each_safe(p, q, &newtbl->hash_buckets[i])
+ tbl->free_node(p, 0);
+ }
+ __mesh_table_free(newtbl);
+endgrow:
+ return NULL;
+}
+
/* This lock will have the grow table function as writer and add / delete nodes
* as readers. When reading the table (i.e. doing lookups) we are well protected
@@ -187,6 +250,8 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data
*/
int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
{
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ struct ieee80211_local *local = sdata->local;
struct mesh_path *mpath, *new_mpath;
struct mpath_node *node, *new_node;
struct hlist_head *bucket;
@@ -195,8 +260,6 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
int err = 0;
u32 hash_idx;
- might_sleep();
-
if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
/* never add ourselves as neighbours */
return -ENOTSUPP;
@@ -208,11 +271,11 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
return -ENOSPC;
err = -ENOMEM;
- new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL);
+ new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
if (!new_mpath)
goto err_path_alloc;
- new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL);
+ new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC);
if (!new_node)
goto err_node_alloc;
@@ -250,20 +313,8 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
spin_unlock(&mesh_paths->hashwlock[hash_idx]);
read_unlock(&pathtbl_resize_lock);
if (grow) {
- struct mesh_table *oldtbl, *newtbl;
-
- write_lock(&pathtbl_resize_lock);
- oldtbl = mesh_paths;
- newtbl = mesh_table_grow(mesh_paths);
- if (!newtbl) {
- write_unlock(&pathtbl_resize_lock);
- return 0;
- }
- rcu_assign_pointer(mesh_paths, newtbl);
- write_unlock(&pathtbl_resize_lock);
-
- synchronize_rcu();
- mesh_table_free(oldtbl, false);
+ set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags);
+ queue_work(local->hw.workqueue, &ifmsh->work);
}
return 0;
@@ -278,9 +329,46 @@ err_path_alloc:
return err;
}
+void mesh_mpath_table_grow(void)
+{
+ struct mesh_table *oldtbl, *newtbl;
+
+ write_lock(&pathtbl_resize_lock);
+ oldtbl = mesh_paths;
+ newtbl = mesh_table_grow(mesh_paths);
+ if (!newtbl) {
+ write_unlock(&pathtbl_resize_lock);
+ return;
+ }
+ rcu_assign_pointer(mesh_paths, newtbl);
+ write_unlock(&pathtbl_resize_lock);
+
+ synchronize_rcu();
+ mesh_table_free(oldtbl, false);
+}
+
+void mesh_mpp_table_grow(void)
+{
+ struct mesh_table *oldtbl, *newtbl;
+
+ write_lock(&pathtbl_resize_lock);
+ oldtbl = mpp_paths;
+ newtbl = mesh_table_grow(mpp_paths);
+ if (!newtbl) {
+ write_unlock(&pathtbl_resize_lock);
+ return;
+ }
+ rcu_assign_pointer(mpp_paths, newtbl);
+ write_unlock(&pathtbl_resize_lock);
+
+ synchronize_rcu();
+ mesh_table_free(oldtbl, false);
+}
int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
{
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ struct ieee80211_local *local = sdata->local;
struct mesh_path *mpath, *new_mpath;
struct mpath_node *node, *new_node;
struct hlist_head *bucket;
@@ -289,8 +377,6 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
int err = 0;
u32 hash_idx;
- might_sleep();
-
if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
/* never add ourselves as neighbours */
return -ENOTSUPP;
@@ -299,11 +385,11 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
return -ENOTSUPP;
err = -ENOMEM;
- new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL);
+ new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
if (!new_mpath)
goto err_path_alloc;
- new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL);
+ new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC);
if (!new_node)
goto err_node_alloc;
@@ -337,20 +423,8 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
spin_unlock(&mpp_paths->hashwlock[hash_idx]);
read_unlock(&pathtbl_resize_lock);
if (grow) {
- struct mesh_table *oldtbl, *newtbl;
-
- write_lock(&pathtbl_resize_lock);
- oldtbl = mpp_paths;
- newtbl = mesh_table_grow(mpp_paths);
- if (!newtbl) {
- write_unlock(&pathtbl_resize_lock);
- return 0;
- }
- rcu_assign_pointer(mpp_paths, newtbl);
- write_unlock(&pathtbl_resize_lock);
-
- synchronize_rcu();
- mesh_table_free(oldtbl, false);
+ set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags);
+ queue_work(local->hw.workqueue, &ifmsh->work);
}
return 0;
--
1.5.4.3
^ permalink raw reply related
* [PATCH] mac80211: Assign a default mesh beaconing interval.
From: Javier Cardona @ 2009-08-08 3:31 UTC (permalink / raw)
To: linux-wireless; +Cc: Javier Cardona, andrey, johannes, linville, devel
In-Reply-To: <1249702314-32504-7-git-send-email-javier@cozybit.com>
Incidentally, this fixes mesh beaconing in mac80211_hwsim devices.
Signed-off-by: Javier Cardona <javier@cozybit.com>
---
net/mac80211/mesh.c | 6 ++++--
net/mac80211/mesh.h | 1 +
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 5202d7c..3b49d39 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -525,9 +525,11 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
struct ieee80211_local *local = sdata->local;
ifmsh->housekeeping = true;
- ieee80211_queue_work(&local->hw, &ifmsh->work);
+ queue_work(local->hw, &ifmsh->work);
+ sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
- BSS_CHANGED_BEACON_ENABLED);
+ BSS_CHANGED_BEACON_ENABLED |
+ BSS_CHANGED_BEACON_INT);
}
void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 6cb3db8..b6ea100 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -174,6 +174,7 @@ struct mesh_rmc {
*/
#define MESH_PATH_REFRESH_TIME 1000
#define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME)
+#define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */
#define MESH_MAX_PREQ_RETRIES 4
#define MESH_PATH_EXPIRE (600 * HZ)
--
1.5.4.3
^ permalink raw reply related
* [PATCH] mac80211: Early detection of broken mesh paths when using minstrel.
From: Javier Cardona @ 2009-08-08 3:31 UTC (permalink / raw)
To: linux-wireless; +Cc: Javier Cardona, andrey, johannes, linville, devel
In-Reply-To: <1249702314-32504-6-git-send-email-javier@cozybit.com>
Signed-off-by: Javier Cardona <javier@cozybit.com>
---
net/mac80211/mesh_hwmp.c | 1 -
net/mac80211/rc80211_minstrel.c | 8 +++++++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index b4309b2..1cd1e72 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -272,7 +272,6 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
}
last_hop_metric = airtime_link_metric_get(local, sta);
- printk("XXX: last_hop_metric = %d\n", last_hop_metric);
/* Update and check originator routing info */
fresh_info = true;
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 3ea9740..0071649 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -51,6 +51,7 @@
#include <linux/random.h>
#include <linux/ieee80211.h>
#include <net/mac80211.h>
+#include "mesh.h"
#include "rate.h"
#include "rc80211_minstrel.h"
@@ -178,9 +179,14 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) {
mi->r[ndx].success += success;
- if (si)
+ if (si) {
si->fail_avg = (18050 - mi->r[ndx].probability)
/ 180;
+ WARN_ON(si->fail_avg > 100);
+ if (si->fail_avg == 100 &&
+ ieee80211_vif_is_mesh(&si->sdata->vif))
+ mesh_plink_broken(si);
+ }
}
}
--
1.5.4.3
^ permalink raw reply related
* [PATCH] mac80211: Update the station failed frames average when minstrel is used.
From: Javier Cardona @ 2009-08-08 3:31 UTC (permalink / raw)
To: linux-wireless; +Cc: Javier Cardona, Andrey Yurovsky, johannes, linville, devel
In-Reply-To: <1249702314-32504-5-git-send-email-javier@cozybit.com>
The fail_avg value is used to compute the mesh metric, and was only being set
by the pid rate control module. This fixes the mesh path selection mechanism
for cards that use mistrel for rate control.
Signed-off-by: Javier Cardona <javier@cozybit.com>
Signed-off-by: Andrey Yurovsky <andrey@cozybit.com>
---
net/mac80211/rc80211_minstrel.c | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 7c51429..3ea9740 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -155,12 +155,16 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
struct sk_buff *skb)
{
struct minstrel_sta_info *mi = priv_sta;
+ struct minstrel_priv *mp = (struct minstrel_priv *)priv;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *ar = info->status.rates;
+ struct ieee80211_local *local = hw_to_local(mp->hw);
+ struct sta_info *si;
int i, ndx;
int success;
success = !!(info->flags & IEEE80211_TX_STAT_ACK);
+ si = sta_info_get(local, sta->addr);
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
if (ar[i].idx < 0)
@@ -172,8 +176,12 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
mi->r[ndx].attempts += ar[i].count;
- if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0))
+ if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) {
mi->r[ndx].success += success;
+ if (si)
+ si->fail_avg = (18050 - mi->r[ndx].probability)
+ / 180;
+ }
}
if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0))
--
1.5.4.3
^ permalink raw reply related
* [PATCH] mac80211: Use 3-address format for mesh broadcast frames.
From: Javier Cardona @ 2009-08-08 3:31 UTC (permalink / raw)
To: linux-wireless; +Cc: Javier Cardona, andrey, johannes, linville, devel
In-Reply-To: <1249702314-32504-4-git-send-email-javier@cozybit.com>
The 11s task group recently changed the frame mesh multicast/broadcast frame
format to use 3-address. This was done to avoid interactions with widely
deployed lazy-WDS access points.
Signed-off-by: Javier Cardona <javier@cozybit.com>
---
net/mac80211/mesh.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++---
net/mac80211/mesh.h | 5 +++-
net/mac80211/rx.c | 45 ++++++++++++++++++++++-------------
net/mac80211/tx.c | 64 +++++++++++++++++++++++++++------------------------
net/wireless/util.c | 16 +++++++++---
5 files changed, 136 insertions(+), 56 deletions(-)
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index d9292a9..5202d7c 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -399,21 +399,75 @@ endgrow:
}
/**
+ * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame
+ * @hdr: 802.11 frame header
+ * @fc: frame control field
+ * @meshda: destination address in the mesh
+ * @meshsa: source address address in the mesh. Same as TA, as frame is
+ * locally originated.
+ *
+ * Return the length of the 802.11 (does not include a mesh control header)
+ */
+int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, char
+ *meshda, char *meshsa) {
+ if (is_multicast_ether_addr(meshda)) {
+ *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
+ /* DA TA SA */
+ memcpy(hdr->addr1, meshda, ETH_ALEN);
+ memcpy(hdr->addr2, meshsa, ETH_ALEN);
+ memcpy(hdr->addr3, meshsa, ETH_ALEN);
+ return 24;
+ } else {
+ *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
+ IEEE80211_FCTL_TODS);
+ /* RA TA DA SA */
+ memset(hdr->addr1, 0, ETH_ALEN); /* RA is resolved later */
+ memcpy(hdr->addr2, meshsa, ETH_ALEN);
+ memcpy(hdr->addr3, meshda, ETH_ALEN);
+ memcpy(hdr->addr4, meshsa, ETH_ALEN);
+ return 30;
+ }
+}
+
+/**
* ieee80211_new_mesh_header - create a new mesh header
* @meshhdr: uninitialized mesh header
* @sdata: mesh interface to be used
+ * @addr4: addr4 of the mesh frame (1st in ae header)
+ * may be NULL
+ * @addr5: addr5 of the mesh frame (1st or 2nd in ae header)
+ * may be NULL unless addr6 is present
+ * @addr6: addr6 of the mesh frame (2nd or 3rd in ae header)
+ * may be NULL unless addr5 is present
*
* Return the header length.
*/
int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
- struct ieee80211_sub_if_data *sdata)
+ struct ieee80211_sub_if_data *sdata, char *addr4,
+ char *addr5, char *addr6)
{
- meshhdr->flags = 0;
+ int aelen = 0;
+ memset(meshhdr, 0, sizeof(meshhdr));
meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum);
sdata->u.mesh.mesh_seqnum++;
-
- return 6;
+ if (addr4) {
+ meshhdr->flags |= MESH_FLAGS_AE_A4;
+ aelen += ETH_ALEN;
+ memcpy(meshhdr->eaddr1, addr4, ETH_ALEN);
+ }
+ if (addr5 && addr6) {
+ meshhdr->flags |= MESH_FLAGS_AE_A5_A6;
+ aelen += 2 * ETH_ALEN;
+ if (!addr4) {
+ memcpy(meshhdr->eaddr1, addr5, ETH_ALEN);
+ memcpy(meshhdr->eaddr2, addr6, ETH_ALEN);
+ } else {
+ memcpy(meshhdr->eaddr2, addr5, ETH_ALEN);
+ memcpy(meshhdr->eaddr3, addr6, ETH_ALEN);
+ }
+ }
+ return 6 + aelen;
}
static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 8e70dae..6cb3db8 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -193,8 +193,11 @@ struct mesh_rmc {
/* Public interfaces */
/* Various */
+int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc,
+ char *da, char *sa);
int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
- struct ieee80211_sub_if_data *sdata);
+ struct ieee80211_sub_if_data *sdata, char *addr4,
+ char *addr5, char *addr6);
int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr,
struct ieee80211_sub_if_data *sdata);
bool mesh_matches_local(struct ieee802_11_elems *ie,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 25a669c..e7d8895 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -489,12 +489,21 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
+ char *dev_addr = rx->dev->dev_addr;
if (ieee80211_is_data(hdr->frame_control)) {
- if (!ieee80211_has_a4(hdr->frame_control))
- return RX_DROP_MONITOR;
- if (memcmp(hdr->addr4, rx->dev->dev_addr, ETH_ALEN) == 0)
- return RX_DROP_MONITOR;
+ if (is_multicast_ether_addr(hdr->addr1)) {
+ if (ieee80211_has_tods(hdr->frame_control) ||
+ !ieee80211_has_fromds(hdr->frame_control))
+ return RX_DROP_MONITOR;
+ if (memcmp(hdr->addr3, dev_addr, ETH_ALEN) == 0)
+ return RX_DROP_MONITOR;
+ } else {
+ if (!ieee80211_has_a4(hdr->frame_control))
+ return RX_DROP_MONITOR;
+ if (memcmp(hdr->addr4, dev_addr, ETH_ALEN) == 0)
+ return RX_DROP_MONITOR;
+ }
}
/* If there is not an established peer link and this is not a peer link
@@ -527,7 +536,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
if (ieee80211_is_data(hdr->frame_control) &&
is_multicast_ether_addr(hdr->addr1) &&
- mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->sdata))
+ mesh_rmc_check(hdr->addr3, msh_h_get(hdr, hdrlen), rx->sdata))
return RX_DROP_MONITOR;
#undef msh_h_get
@@ -1495,7 +1504,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
/* illegal frame */
return RX_DROP_MONITOR;
- if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){
+ if (!is_multicast_ether_addr(hdr->addr1) &&
+ (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6)) {
struct mesh_path *mppath;
rcu_read_lock();
@@ -1512,7 +1522,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
rcu_read_unlock();
}
- if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0)
+ /* Frame has reached destination. Don't forward */
+ if (!is_multicast_ether_addr(hdr->addr1) &&
+ compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0)
return RX_CONTINUE;
mesh_hdr->ttl--;
@@ -1532,22 +1544,21 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
rx->dev->name);
fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
- /*
- * Save TA to addr1 to send TA a path error if a
- * suitable next hop is not found
- */
- memcpy(fwd_hdr->addr1, fwd_hdr->addr2, ETH_ALEN);
memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN);
info = IEEE80211_SKB_CB(fwd_skb);
memset(info, 0, sizeof(*info));
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
info->control.vif = &rx->sdata->vif;
ieee80211_select_queue(local, fwd_skb);
- if (is_multicast_ether_addr(fwd_hdr->addr3))
- memcpy(fwd_hdr->addr1, fwd_hdr->addr3,
+ if (!is_multicast_ether_addr(fwd_hdr->addr1)) {
+ int err;
+ /*
+ * Save TA to addr1 to send TA a path error if a
+ * suitable next hop is not found
+ */
+ memcpy(fwd_hdr->addr1, fwd_hdr->addr2,
ETH_ALEN);
- else {
- int err = mesh_nexthop_lookup(fwd_skb, sdata);
+ err = mesh_nexthop_lookup(fwd_skb, sdata);
/* Failed to immediately resolve next hop:
* fwded frame was dropped or will be added
* later to the pending skb queue. */
@@ -1560,7 +1571,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
}
}
- if (is_multicast_ether_addr(hdr->addr3) ||
+ if (is_multicast_ether_addr(hdr->addr1) ||
rx->dev->flags & IFF_PROMISC)
return RX_CONTINUE;
else
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 0df5a96..a97d541 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1461,9 +1461,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
if (ieee80211_vif_is_mesh(&sdata->vif) &&
ieee80211_is_data(hdr->frame_control)) {
- if (is_multicast_ether_addr(hdr->addr3))
- memcpy(hdr->addr1, hdr->addr3, ETH_ALEN);
- else
+ if (!is_multicast_ether_addr(hdr->addr1))
if (mesh_nexthop_lookup(skb, sdata)) {
dev_put(sdata->dev);
return;
@@ -1666,52 +1664,58 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
break;
#ifdef CONFIG_MAC80211_MESH
case NL80211_IFTYPE_MESH_POINT:
- fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
if (!sdata->u.mesh.mshcfg.dot11MeshTTL) {
/* Do not send frames with mesh_ttl == 0 */
sdata->u.mesh.mshstats.dropped_frames_ttl++;
ret = 0;
goto fail;
}
- memset(&mesh_hdr, 0, sizeof(mesh_hdr));
if (compare_ether_addr(dev->dev_addr,
skb->data + ETH_ALEN) == 0) {
- /* RA TA DA SA */
- memset(hdr.addr1, 0, ETH_ALEN);
- memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
- memcpy(hdr.addr3, skb->data, ETH_ALEN);
- memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
- meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata);
+ hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
+ skb->data, skb->data + ETH_ALEN);
+ meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
+ sdata, NULL, NULL, NULL);
} else {
/* packet from other interface */
struct mesh_path *mppath;
+ int is_mesh_mcast = 1;
+ char *mesh_da;
- memset(hdr.addr1, 0, ETH_ALEN);
- memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
- memcpy(hdr.addr4, dev->dev_addr, ETH_ALEN);
-
+ rcu_read_lock();
if (is_multicast_ether_addr(skb->data))
- memcpy(hdr.addr3, skb->data, ETH_ALEN);
+ /* DA TA mSA AE:SA */
+ mesh_da = skb->data;
else {
- rcu_read_lock();
mppath = mpp_path_lookup(skb->data, sdata);
- if (mppath)
- memcpy(hdr.addr3, mppath->mpp, ETH_ALEN);
- else
- memset(hdr.addr3, 0xff, ETH_ALEN);
- rcu_read_unlock();
+ if (mppath) {
+ /* RA TA mDA mSA AE:DA SA */
+ mesh_da = mppath->mpp;
+ is_mesh_mcast = 0;
+ } else
+ /* DA TA mSA AE:SA */
+ mesh_da = dev->broadcast;
}
+ hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
+ mesh_da, dev->dev_addr);
+ rcu_read_unlock();
+ if (is_mesh_mcast)
+ meshhdrlen =
+ ieee80211_new_mesh_header(&mesh_hdr,
+ sdata,
+ skb->data + ETH_ALEN,
+ NULL,
+ NULL);
+ else
+ meshhdrlen =
+ ieee80211_new_mesh_header(&mesh_hdr,
+ sdata,
+ NULL,
+ skb->data,
+ skb->data + ETH_ALEN);
- mesh_hdr.flags |= MESH_FLAGS_AE_A5_A6;
- mesh_hdr.ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
- put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &mesh_hdr.seqnum);
- memcpy(mesh_hdr.eaddr1, skb->data, ETH_ALEN);
- memcpy(mesh_hdr.eaddr2, skb->data + ETH_ALEN, ETH_ALEN);
- sdata->u.mesh.mesh_seqnum++;
- meshhdrlen = 18;
}
- hdrlen = 30;
break;
#endif
case NL80211_IFTYPE_STATION:
diff --git a/net/wireless/util.c b/net/wireless/util.c
index ba387d8..693275a 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -274,11 +274,11 @@ static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
switch (ae) {
case 0:
return 6;
- case 1:
+ case MESH_FLAGS_AE_A4:
return 12;
- case 2:
+ case MESH_FLAGS_AE_A5_A6:
return 18;
- case 3:
+ case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6):
return 24;
default:
return 6;
@@ -333,10 +333,18 @@ int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr,
}
break;
case cpu_to_le16(IEEE80211_FCTL_FROMDS):
- if (iftype != NL80211_IFTYPE_STATION ||
+ if ((iftype != NL80211_IFTYPE_STATION &&
+ iftype != NL80211_IFTYPE_MESH_POINT) ||
(is_multicast_ether_addr(dst) &&
!compare_ether_addr(src, addr)))
return -1;
+ if (iftype == NL80211_IFTYPE_MESH_POINT) {
+ struct ieee80211s_hdr *meshdr =
+ (struct ieee80211s_hdr *) (skb->data + hdrlen);
+ hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
+ if (meshdr->flags & MESH_FLAGS_AE_A4)
+ memcpy(src, meshdr->eaddr1, ETH_ALEN);
+ }
break;
case cpu_to_le16(0):
if (iftype != NL80211_IFTYPE_ADHOC)
--
1.5.4.3
^ permalink raw reply related
* [PATCH] mac80211: Simulate transmission losses on plinks to aid in testing mesh metrics.
From: Javier Cardona @ 2009-08-08 3:31 UTC (permalink / raw)
To: linux-wireless; +Cc: Javier Cardona, Andrey Yurovsky, johannes, linville, devel
In-Reply-To: <1249702314-32504-3-git-send-email-javier@cozybit.com>
This enables us to specify a simulated loss probability per mesh peer link.
Useful to simulate and test different mesh topologies and test different mesh
metrics.
The simulated loss rate setting can be configured as a plink action. The
intended use is:
iw dev mesh station set <MAC> plink_action loss 25
Signed-off-by: Andrey Yurovsky <andrey@cozybit.com>
Signed-off-by: Javier Cardona <javier@cozybit.com>
---
include/linux/nl80211.h | 4 +++
include/net/cfg80211.h | 4 +++
net/mac80211/cfg.c | 6 +++++
net/mac80211/mesh.c | 1 +
net/mac80211/mesh.h | 1 +
net/mac80211/mesh_hwmp.c | 1 +
net/mac80211/mesh_plink.c | 6 +++++
net/mac80211/sta_info.h | 1 +
net/mac80211/tx.c | 54 +++++++++++++++++++++++++++++++++++++++++++-
net/wireless/nl80211.c | 9 +++++++
10 files changed, 85 insertions(+), 2 deletions(-)
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index a8d71ed..3de615b 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -713,6 +713,7 @@ enum nl80211_attrs {
NL80211_ATTR_KEYS,
NL80211_ATTR_PID,
+ NL80211_ATTR_SIM_LOSS,
/* add attributes here, update the policy in nl80211.c */
@@ -1198,6 +1199,8 @@ enum nl80211_mntr_flags {
*
* @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
*
+ * @NL80211_MESHCONF_SIM_LOSS_RATE: simulated loss rate at this MP.
+ *
* @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
*/
enum nl80211_meshconf_params {
@@ -1215,6 +1218,7 @@ enum nl80211_meshconf_params {
NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
+ NL80211_MESHCONF_SIM_LOSS_RATE,
/* keep last */
__NL80211_MESHCONF_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index d5756c9..6bc5957 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -265,6 +265,7 @@ enum plink_actions {
PLINK_ACTION_INVALID,
PLINK_ACTION_OPEN,
PLINK_ACTION_BLOCK,
+ PLINK_ACTION_LOSS,
};
/**
@@ -282,6 +283,7 @@ enum plink_actions {
* (bitmask of BIT(NL80211_STA_FLAG_...))
* @listen_interval: listen interval or -1 for no change
* @aid: AID or zero for no change
+ * @sim_loss_rate: simulated TX probable loss percentage
*/
struct station_parameters {
u8 *supported_rates;
@@ -292,6 +294,7 @@ struct station_parameters {
u8 supported_rates_len;
u8 plink_action;
struct ieee80211_ht_cap *ht_capa;
+ u8 sim_loss_rate;
};
/**
@@ -508,6 +511,7 @@ struct mesh_config {
u32 dot11MeshHWMPactivePathTimeout;
u16 dot11MeshHWMPpreqMinInterval;
u16 dot11MeshHWMPnetDiameterTraversalTime;
+ u8 dot11MeshSimLossRate;
};
/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5608f6c..8067f66 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -693,6 +693,9 @@ static void sta_apply_parameters(struct ieee80211_local *local,
case PLINK_ACTION_BLOCK:
mesh_plink_block(sta);
break;
+ case PLINK_ACTION_LOSS:
+ mesh_plink_sim_loss(sta, params->sim_loss_rate);
+ break;
}
}
}
@@ -1043,6 +1046,9 @@ static int ieee80211_set_mesh_params(struct wiphy *wiphy,
mask))
conf->dot11MeshHWMPnetDiameterTraversalTime =
nconf->dot11MeshHWMPnetDiameterTraversalTime;
+ if (_chg_mesh_attr(NL80211_MESHCONF_SIM_LOSS_RATE, mask))
+ conf->dot11MeshSimLossRate =
+ nconf->dot11MeshSimLossRate;
return 0;
}
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 8c068e2..d9292a9 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -653,6 +653,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
MESH_PATH_REFRESH_TIME;
ifmsh->mshcfg.min_discovery_timeout =
MESH_MIN_DISCOVERY_TIMEOUT;
+ ifmsh->mshcfg.dot11MeshSimLossRate = 0;
ifmsh->accepting_plinks = true;
ifmsh->preq_id = 0;
ifmsh->dsn = 0;
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 6aaf1ec..8e70dae 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -238,6 +238,7 @@ void mesh_plink_broken(struct sta_info *sta);
void mesh_plink_deactivate(struct sta_info *sta);
int mesh_plink_open(struct sta_info *sta);
void mesh_plink_block(struct sta_info *sta);
+void mesh_plink_sim_loss(struct sta_info *sta, u8 rate);
void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt, size_t len,
struct ieee80211_rx_status *rx_status);
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 1cd1e72..b4309b2 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -272,6 +272,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
}
last_hop_metric = airtime_link_metric_get(local, sta);
+ printk("XXX: last_hop_metric = %d\n", last_hop_metric);
/* Update and check originator routing info */
fresh_info = true;
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index cb14253..7c49c95 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -382,6 +382,12 @@ void mesh_plink_block(struct sta_info *sta)
spin_unlock_bh(&sta->lock);
}
+void mesh_plink_sim_loss(struct sta_info *sta, u8 rate)
+{
+ spin_lock_bh(&sta->lock);
+ sta->plink_sim_loss = rate;
+ spin_unlock_bh(&sta->lock);
+}
void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt,
size_t len, struct ieee80211_rx_status *rx_status)
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index ccc3adf..a248a8b 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -294,6 +294,7 @@ struct sta_info {
bool ignore_plink_timer;
bool plink_timer_was_running;
enum plink_state plink_state;
+ u8 plink_sim_loss;
u32 plink_timeout;
struct timer_list plink_timer;
#endif
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index c9be9dc..0df5a96 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -18,6 +18,7 @@
#include <linux/etherdevice.h>
#include <linux/bitmap.h>
#include <linux/rcupdate.h>
+#include <linux/random.h>
#include <net/net_namespace.h>
#include <net/ieee80211_radiotap.h>
#include <net/cfg80211.h>
@@ -39,6 +40,47 @@
/* misc utils */
+/* Decide whether we should simulate the loss of a frame based on the simulated
+ * plink loss probability and the frame's destination. Used for testing.
+ *
+ * Must be invoked with the rcu read lock held.
+ * */
+static int random_tx_loss(struct ieee80211_sub_if_data *sdata, struct
+ ieee80211_hdr *hdr)
+{
+ struct sta_info *sta;
+ u8 r = 0;
+
+ get_random_bytes(&r, sizeof(r));
+
+ list_for_each_entry(sta, &sdata->local->sta_list, list) {
+ if (!memcmp(sta->sta.addr, hdr->addr1, 6))
+ if (r*25 < sta->plink_sim_loss*64)
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static int simulate_tx_loss(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_hdr *hdr, struct sk_buff *skb)
+{
+ struct ieee80211_hw *hw = &sdata->local->hw;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+ ieee80211_tx_info_clear_status(info);
+ info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS;
+
+ info->status.rates[0].idx = 0;
+ info->status.rates[0].count = hw->max_rate_tries;
+
+ ieee80211_tx_status_irqsafe(hw, skb);
+
+ /* this will ensure that the frame is not queued in the tx path */
+ return IEEE80211_TX_OK;
+}
+
static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
int next_frag_len)
{
@@ -1244,6 +1286,7 @@ static void ieee80211_tx(struct ieee80211_sub_if_data *sdata,
struct ieee80211_tx_data tx;
ieee80211_tx_result res_prepare;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct sk_buff *next;
unsigned long flags;
int ret, retries;
@@ -1278,7 +1321,10 @@ static void ieee80211_tx(struct ieee80211_sub_if_data *sdata,
retries = 0;
retry:
- ret = __ieee80211_tx(local, &tx.skb, tx.sta, txpending);
+ if (ieee80211_vif_is_mesh(&sdata->vif) && random_tx_loss(sdata, hdr))
+ ret = simulate_tx_loss(sdata, hdr, skb);
+ else
+ ret = __ieee80211_tx(local, &tx.skb, tx.sta, txpending);
switch (ret) {
case IEEE80211_TX_OK:
break;
@@ -1857,7 +1903,11 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
hdr = (struct ieee80211_hdr *)skb->data;
sta = sta_info_get(local, hdr->addr1);
- ret = __ieee80211_tx(local, &skb, sta, true);
+ if (ieee80211_vif_is_mesh(&sdata->vif) &&
+ random_tx_loss(sdata, hdr))
+ ret = simulate_tx_loss(sdata, hdr, skb);
+ else
+ ret = __ieee80211_tx(local, &skb, sta, true);
if (ret != IEEE80211_TX_OK)
result = false;
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 667a87d..1dfe8ea 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1878,6 +1878,10 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
params.plink_action =
nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
+ if (info->attrs[NL80211_ATTR_SIM_LOSS])
+ params.sim_loss_rate =
+ nla_get_u8(info->attrs[NL80211_ATTR_SIM_LOSS]);
+
rtnl_lock();
err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
@@ -2619,6 +2623,8 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
cur_params.dot11MeshHWMPpreqMinInterval);
NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
cur_params.dot11MeshHWMPnetDiameterTraversalTime);
+ NLA_PUT_U8(msg, NL80211_MESHCONF_SIM_LOSS_RATE,
+ cur_params.dot11MeshSimLossRate);
nla_nest_end(msg, pinfoattr);
genlmsg_end(msg, hdr);
err = genlmsg_reply(msg, info);
@@ -2661,6 +2667,7 @@ nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] __read_mostly = {
[NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
[NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 },
[NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 },
+ [NL80211_MESHCONF_SIM_LOSS_RATE] = { .type = NLA_U8 },
};
static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
@@ -2729,6 +2736,8 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
dot11MeshHWMPnetDiameterTraversalTime,
mask, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
nla_get_u16);
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshSimLossRate,
+ mask, NL80211_MESHCONF_SIM_LOSS_RATE, nla_get_u8);
/* Apply changes */
err = rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask);
--
1.5.4.3
^ permalink raw reply related
* [PATCH] mac80211: Use correct sign for mesh active path refresh.
From: Javier Cardona @ 2009-08-08 3:31 UTC (permalink / raw)
To: linux-wireless; +Cc: Andrey Yurovsky, Javier Cardona, johannes, linville, devel
In-Reply-To: <1249702314-32504-2-git-send-email-javier@cozybit.com>
From: Andrey Yurovsky <andrey@cozybit.com>
On locally originated traffic, we refresh active paths after a timeout. The
decision to do this was using the wrong sign and therefore the refresh timer
was triggered for every frame.
Signed-off-by: Andrey Yurovsky <andrey@cozybit.com>
Signed-off-by: Javier Cardona <javier@cozybit.com>
---
net/mac80211/mesh_hwmp.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index b54c21c..1cd1e72 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -791,7 +791,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
}
if (mpath->flags & MESH_PATH_ACTIVE) {
- if (time_after(jiffies, mpath->exp_time -
+ if (time_after(jiffies, mpath->exp_time +
msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time))
&& !memcmp(sdata->dev->dev_addr, hdr->addr4,
ETH_ALEN)
--
1.5.4.3
^ permalink raw reply related
* [PATCH] mac80211: Improve dequeing from mpath frame queue.
From: Javier Cardona @ 2009-08-08 3:31 UTC (permalink / raw)
To: linux-wireless; +Cc: Andrey Yurovsky, Javier Cardona, johannes, linville, devel
In-Reply-To: <1249702314-32504-1-git-send-email-javier@cozybit.com>
From: Andrey Yurovsky <andrey@cozybit.com>
Also, fix typo in comment.
Signed-off-by: Javier Cardona <javier@cozybit.com>
Signed-off-by: Andrey Yurovsky <andrey@cozybit.com>
---
net/mac80211/mesh.h | 2 +-
net/mac80211/mesh_hwmp.c | 6 ++----
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index ce53881..6aaf1ec 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -61,7 +61,7 @@ enum mesh_path_flags {
* retry
* @discovery_retries: number of discovery retries
* @flags: mesh path flags, as specified on &enum mesh_path_flags
- * @state_lock: mesh pat state lock
+ * @state_lock: mesh path state lock
*
*
* The combination of dst and sdata is unique in the mesh path table. Since the
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index e1a763e..b54c21c 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -810,10 +810,8 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
}
if (skb_queue_len(&mpath->frame_queue) >=
- MESH_FRAME_QUEUE_LEN) {
- skb_to_free = mpath->frame_queue.next;
- skb_unlink(skb_to_free, &mpath->frame_queue);
- }
+ MESH_FRAME_QUEUE_LEN)
+ skb_to_free = skb_dequeue(&mpath->frame_queue);
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
skb_queue_tail(&mpath->frame_queue, skb);
--
1.5.4.3
^ permalink raw reply related
* Mesh fixes and improvements
From: Javier Cardona @ 2009-08-08 3:31 UTC (permalink / raw)
To: linux-wireless; +Cc: andrey, johannes, linville, devel
This series includes some fixes, testing aids and improvements to the mesh
stack. It is important to note that the patch
"Use-3-address-format-for-mesh-broadcast-frames" breaks compatibility with
previous versions. This is unavoidable and will keep happening as new versions
of the 802.11s drafts are produced.
Also, I'm not sure if "Simulate-transmission-losses-on-plinks-to-..." should be
merged upstream, but we find it really useful to test mesh configurations.
Please comment if you have different opinions on its adequacy or
implementation.
Cheers,
Javier
include/linux/nl80211.h | 4 +
include/net/cfg80211.h | 4 +
net/mac80211/Kconfig | 1 -
net/mac80211/cfg.c | 6 ++
net/mac80211/ieee80211_i.h | 2 +-
net/mac80211/mesh.c | 138 ++++++++++++++++++------------------
net/mac80211/mesh.h | 29 +++++++-
net/mac80211/mesh_hwmp.c | 8 +--
net/mac80211/mesh_pathtbl.c | 146 +++++++++++++++++++++++++++++----------
net/mac80211/mesh_plink.c | 6 ++
net/mac80211/rc80211_minstrel.c | 16 ++++-
net/mac80211/rx.c | 45 ++++++++-----
net/mac80211/sta_info.h | 1 +
net/mac80211/tx.c | 118 +++++++++++++++++++++++---------
net/wireless/nl80211.c | 9 +++
net/wireless/util.c | 16 +++-
16 files changed, 380 insertions(+), 169 deletions(-)
^ permalink raw reply
* Re: [PATCH 0/3] roaming/disassoc fixes
From: Pavel Roskin @ 2009-08-08 3:34 UTC (permalink / raw)
To: Johannes Berg; +Cc: John Linville, linux-wireless
In-Reply-To: <20090806184131.114246687@sipsolutions.net>
On Thu, 2009-08-06 at 20:41 +0200, Johannes Berg wrote:
> Pavel reported a bug, and it was hard to fix :)
>
> Here's the fix patchset, including another fix
> for a bug I noticed while testing.
>
> This requires Pavel's patch, of course, but applies
> without it in the tree too.
I'm getting a reasonable behavior in the managed mode now. Thank you!
--
Regards,
Pavel Roskin
^ permalink raw reply
* [PATCH 15/16] iwlwifi: automatically adjust sleep level
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Reinette Chatre
In-Reply-To: <1249684912-22936-1-git-send-email-reinette.chatre@intel.com>
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
* [PATCH 14/16] iwlwifi: display correct critical temperature infomation
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1249684912-22936-1-git-send-email-reinette.chatre@intel.com>
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
* [PATCH 16/16] iwlwifi: disable powersave mode
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1249684912-22936-1-git-send-email-reinette.chatre@intel.com>
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
* [PATCH 11/16] iwlwifi: handle the case when set power fail
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1249684912-22936-1-git-send-email-reinette.chatre@intel.com>
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
* [PATCH 12/16] iwlwifi: refactor some thermal throttle code
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Reinette Chatre
In-Reply-To: <1249684912-22936-1-git-send-email-reinette.chatre@intel.com>
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
* [PATCH 13/16] iwlwifi: fix missing EXPORT_SYMBOL
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, ipw3945-devel, Reinette Chatre
In-Reply-To: <1249684912-22936-1-git-send-email-reinette.chatre@intel.com>
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
* [PATCH 10/16] iwlwifi: fix legacy thermal throttling power index
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1249684912-22936-1-git-send-email-reinette.chatre@intel.com>
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
* [PATCH 07/16] iwlwifi: Display sensitivity and chain noise information
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1249684912-22936-1-git-send-email-reinette.chatre@intel.com>
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
* [PATCH 09/16] iwlwifi: fix thermal throttling locking problem
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1249684912-22936-1-git-send-email-reinette.chatre@intel.com>
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
* [PATCH 08/16] iwlwifi: revert uCode Alive notification with timeout
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, ipw3945-devel, Reinette Chatre
In-Reply-To: <1249684912-22936-1-git-send-email-reinette.chatre@intel.com>
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
* [PATCH 05/16] iwlwifi: tx/rx queue pointer information
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
In-Reply-To: <1249684912-22936-1-git-send-email-reinette.chatre@intel.com>
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
* [PATCH 06/16] iwlwifi: uCode statistics notification counter
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1249684912-22936-1-git-send-email-reinette.chatre@intel.com>
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
* [PATCH 02/16] iwlwifi: name changed from "fat" to "ht40"
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1249684912-22936-1-git-send-email-reinette.chatre@intel.com>
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
* [PATCH 03/16] iwlwifi: new debugging feature for dumping data traffic
From: Reinette Chatre @ 2009-08-07 22:41 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1249684912-22936-1-git-send-email-reinette.chatre@intel.com>
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
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox