summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZefir Kurtisi <zefir.kurtisi@neratec.com>2012-04-20 17:20:34 +0200
committerJohn W. Linville <linville@tuxdriver.com>2012-04-23 15:37:41 -0400
commitb96f20b3afff36f30baa1e1e121ccbf7518a988d (patch)
treec9d58d8719c06b42ef50efb53552c101f995c305
parent2a5783b817c90ce6fb82a21e103335d1ecbac430 (diff)
ath9k: extend DFS detector stats in dfs_debugfs
Extend debugfs entry for dfs_stats with DFS detection events and shared pool statistics. Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_debug.c46
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_debug.h45
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_pri_detector.c20
4 files changed, 104 insertions, 11 deletions
diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c
index 92891f5fd454..ecc81792f2dc 100644
--- a/drivers/net/wireless/ath/ath9k/dfs.c
+++ b/drivers/net/wireless/ath/ath9k/dfs.c
@@ -148,11 +148,13 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
+ DFS_STAT_INC(sc, pulses_total);
if ((rs->rs_phyerr != ATH9K_PHYERR_RADAR) &&
(rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT)) {
ath_dbg(common, DFS,
"Error: rs_phyer=0x%x not a radar error\n",
rs->rs_phyerr);
+ DFS_STAT_INC(sc, pulses_no_dfs);
return;
}
@@ -188,7 +190,9 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
"width=%d, rssi=%d, delta_ts=%llu\n",
pe.freq, pe.ts, pe.width, pe.rssi, pe.ts-last_ts);
last_ts = pe.ts;
+ DFS_STAT_INC(sc, pulses_processed);
if (pd != NULL && pd->add_pulse(pd, &pe)) {
+ DFS_STAT_INC(sc, radar_detected);
/*
* TODO: forward radar event to DFS management layer
*/
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.c b/drivers/net/wireless/ath/ath9k/dfs_debug.c
index 4364c103ed33..55d28072adeb 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_debug.c
+++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c
@@ -21,9 +21,15 @@
#include "ath9k.h"
#include "dfs_debug.h"
+
+struct ath_dfs_pool_stats global_dfs_pool_stats = { 0 };
+
#define ATH9K_DFS_STAT(s, p) \
len += snprintf(buf + len, size - len, "%28s : %10u\n", s, \
sc->debug.stats.dfs_stats.p);
+#define ATH9K_DFS_POOL_STAT(s, p) \
+ len += snprintf(buf + len, size - len, "%28s : %10u\n", s, \
+ global_dfs_pool_stats.p);
static ssize_t read_file_dfs(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -43,6 +49,9 @@ static ssize_t read_file_dfs(struct file *file, char __user *user_buf,
hw_ver->macVersion, hw_ver->macRev,
(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_DFS) ?
"enabled" : "disabled");
+ len += snprintf(buf + len, size - len, "Pulse detector statistics:\n");
+ ATH9K_DFS_STAT("pulse events reported ", pulses_total);
+ ATH9K_DFS_STAT("invalid pulse events ", pulses_no_dfs);
ATH9K_DFS_STAT("DFS pulses detected ", pulses_detected);
ATH9K_DFS_STAT("Datalen discards ", datalen_discards);
ATH9K_DFS_STAT("RSSI discards ", rssi_discards);
@@ -50,6 +59,18 @@ static ssize_t read_file_dfs(struct file *file, char __user *user_buf,
ATH9K_DFS_STAT("Primary channel pulses ", pri_phy_errors);
ATH9K_DFS_STAT("Secondary channel pulses", ext_phy_errors);
ATH9K_DFS_STAT("Dual channel pulses ", dc_phy_errors);
+ len += snprintf(buf + len, size - len, "Radar detector statistics "
+ "(current DFS region: %d)\n", sc->dfs_detector->region);
+ ATH9K_DFS_STAT("Pulse events processed ", pulses_processed);
+ ATH9K_DFS_STAT("Radars detected ", radar_detected);
+ len += snprintf(buf + len, size - len, "Global Pool statistics:\n");
+ ATH9K_DFS_POOL_STAT("Pool references ", pool_reference);
+ ATH9K_DFS_POOL_STAT("Pulses allocated ", pulse_allocated);
+ ATH9K_DFS_POOL_STAT("Pulses alloc error ", pulse_alloc_error);
+ ATH9K_DFS_POOL_STAT("Pulses in use ", pulse_used);
+ ATH9K_DFS_POOL_STAT("Seqs. allocated ", pseq_allocated);
+ ATH9K_DFS_POOL_STAT("Seqs. alloc error ", pseq_alloc_error);
+ ATH9K_DFS_POOL_STAT("Seqs. in use ", pseq_used);
if (len > size)
len = size;
@@ -60,8 +81,33 @@ static ssize_t read_file_dfs(struct file *file, char __user *user_buf,
return retval;
}
+/* magic number to prevent accidental reset of DFS statistics */
+#define DFS_STATS_RESET_MAGIC 0x80000000
+static ssize_t write_file_dfs(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ unsigned long val;
+ char buf[32];
+ ssize_t len;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+ if (strict_strtoul(buf, 0, &val))
+ return -EINVAL;
+
+ if (val == DFS_STATS_RESET_MAGIC)
+ memset(&sc->debug.stats.dfs_stats, 0,
+ sizeof(sc->debug.stats.dfs_stats));
+ return count;
+}
+
static const struct file_operations fops_dfs_stats = {
.read = read_file_dfs,
+ .write = write_file_dfs,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.h b/drivers/net/wireless/ath/ath9k/dfs_debug.h
index 4911724cb445..e36810a4b585 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_debug.h
+++ b/drivers/net/wireless/ath/ath9k/dfs_debug.h
@@ -22,17 +22,23 @@
#include "hw.h"
/**
- * struct ath_dfs_stats - DFS Statistics
- *
- * @pulses_detected: No. of pulses detected so far
- * @datalen_discards: No. of pulses discarded due to invalid datalen
- * @rssi_discards: No. of pulses discarded due to invalid RSSI
- * @bwinfo_discards: No. of pulses discarded due to invalid BW info
- * @pri_phy_errors: No. of pulses reported for primary channel
- * @ext_phy_errors: No. of pulses reported for extension channel
- * @dc_phy_errors: No. of pulses reported for primary + extension channel
+ * struct ath_dfs_stats - DFS Statistics per wiphy
+ * @pulses_total: pulses reported by HW
+ * @pulses_no_dfs: pulses wrongly reported as DFS
+ * @pulses_detected: pulses detected so far
+ * @datalen_discards: pulses discarded due to invalid datalen
+ * @rssi_discards: pulses discarded due to invalid RSSI
+ * @bwinfo_discards: pulses discarded due to invalid BW info
+ * @pri_phy_errors: pulses reported for primary channel
+ * @ext_phy_errors: pulses reported for extension channel
+ * @dc_phy_errors: pulses reported for primary + extension channel
+ * @pulses_processed: pulses forwarded to detector
+ * @radar_detected: radars detected
*/
struct ath_dfs_stats {
+ /* pulse stats */
+ u32 pulses_total;
+ u32 pulses_no_dfs;
u32 pulses_detected;
u32 datalen_discards;
u32 rssi_discards;
@@ -40,18 +46,39 @@ struct ath_dfs_stats {
u32 pri_phy_errors;
u32 ext_phy_errors;
u32 dc_phy_errors;
+ /* pattern detection stats */
+ u32 pulses_processed;
+ u32 radar_detected;
};
+/**
+ * struct ath_dfs_pool_stats - DFS Statistics for global pools
+ */
+struct ath_dfs_pool_stats {
+ u32 pool_reference;
+ u32 pulse_allocated;
+ u32 pulse_alloc_error;
+ u32 pulse_used;
+ u32 pseq_allocated;
+ u32 pseq_alloc_error;
+ u32 pseq_used;
+};
#if defined(CONFIG_ATH9K_DFS_DEBUGFS)
#define DFS_STAT_INC(sc, c) (sc->debug.stats.dfs_stats.c++)
void ath9k_dfs_init_debug(struct ath_softc *sc);
+#define DFS_POOL_STAT_INC(c) (global_dfs_pool_stats.c++)
+#define DFS_POOL_STAT_DEC(c) (global_dfs_pool_stats.c--)
+extern struct ath_dfs_pool_stats global_dfs_pool_stats;
+
#else
#define DFS_STAT_INC(sc, c) do { } while (0)
static inline void ath9k_dfs_init_debug(struct ath_softc *sc) { }
+#define DFS_POOL_STAT_INC(c) do { } while (0)
+#define DFS_POOL_STAT_DEC(c) do { } while (0)
#endif /* CONFIG_ATH9K_DFS_DEBUGFS */
#endif /* ATH9K_DFS_DEBUG_H */
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
index ecb6334fd20f..91b8dceeadb1 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
+++ b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
@@ -17,8 +17,10 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include "ath9k.h"
#include "dfs_pattern_detector.h"
#include "dfs_pri_detector.h"
+#include "dfs_debug.h"
/**
* struct pri_sequence - sequence of pulses matching one PRI
@@ -101,6 +103,7 @@ static void pool_register_ref(void)
{
spin_lock_bh(&pool_lock);
singleton_pool_references++;
+ DFS_POOL_STAT_INC(pool_reference);
spin_unlock_bh(&pool_lock);
}
@@ -108,6 +111,7 @@ static void pool_deregister_ref(void)
{
spin_lock_bh(&pool_lock);
singleton_pool_references--;
+ DFS_POOL_STAT_DEC(pool_reference);
if (singleton_pool_references == 0) {
/* free singleton pools with no references left */
struct pri_sequence *ps, *ps0;
@@ -115,10 +119,12 @@ static void pool_deregister_ref(void)
list_for_each_entry_safe(p, p0, &pulse_pool, head) {
list_del(&p->head);
+ DFS_POOL_STAT_DEC(pulse_allocated);
kfree(p);
}
list_for_each_entry_safe(ps, ps0, &pseq_pool, head) {
list_del(&ps->head);
+ DFS_POOL_STAT_DEC(pseq_allocated);
kfree(ps);
}
}
@@ -129,6 +135,7 @@ static void pool_put_pulse_elem(struct pulse_elem *pe)
{
spin_lock_bh(&pool_lock);
list_add(&pe->head, &pulse_pool);
+ DFS_POOL_STAT_DEC(pulse_used);
spin_unlock_bh(&pool_lock);
}
@@ -136,6 +143,7 @@ static void pool_put_pseq_elem(struct pri_sequence *pse)
{
spin_lock_bh(&pool_lock);
list_add(&pse->head, &pseq_pool);
+ DFS_POOL_STAT_DEC(pseq_used);
spin_unlock_bh(&pool_lock);
}
@@ -146,6 +154,7 @@ static struct pri_sequence *pool_get_pseq_elem(void)
if (!list_empty(&pseq_pool)) {
pse = list_first_entry(&pseq_pool, struct pri_sequence, head);
list_del(&pse->head);
+ DFS_POOL_STAT_INC(pseq_used);
}
spin_unlock_bh(&pool_lock);
return pse;
@@ -158,6 +167,7 @@ static struct pulse_elem *pool_get_pulse_elem(void)
if (!list_empty(&pulse_pool)) {
pe = list_first_entry(&pulse_pool, struct pulse_elem, head);
list_del(&pe->head);
+ DFS_POOL_STAT_INC(pulse_used);
}
spin_unlock_bh(&pool_lock);
return pe;
@@ -210,9 +220,11 @@ static bool pulse_queue_enqueue(struct pri_detector *pde, u64 ts)
if (p == NULL) {
p = kmalloc(sizeof(*p), GFP_KERNEL);
if (p == NULL) {
- pr_err("failed to allocate pulse_elem\n");
+ DFS_POOL_STAT_INC(pulse_alloc_error);
return false;
}
+ DFS_POOL_STAT_INC(pulse_allocated);
+ DFS_POOL_STAT_INC(pulse_used);
}
INIT_LIST_HEAD(&p->head);
p->ts = ts;
@@ -288,8 +300,12 @@ static bool pseq_handler_create_sequences(struct pri_detector *pde,
new_ps = pool_get_pseq_elem();
if (new_ps == NULL) {
new_ps = kmalloc(sizeof(*new_ps), GFP_KERNEL);
- if (new_ps == NULL)
+ if (new_ps == NULL) {
+ DFS_POOL_STAT_INC(pseq_alloc_error);
return false;
+ }
+ DFS_POOL_STAT_INC(pseq_allocated);
+ DFS_POOL_STAT_INC(pseq_used);
}
memcpy(new_ps, &ps, sizeof(ps));
INIT_LIST_HEAD(&new_ps->head);