Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b96f20b3 authored by Zefir Kurtisi's avatar Zefir Kurtisi Committed by John W. Linville
Browse files

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: default avatarZefir Kurtisi <zefir.kurtisi@neratec.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 2a5783b8
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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
			 */
+46 −0
Original line number Diff line number Diff line
@@ -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,
+36 −9
Original line number Diff line number Diff line
@@ -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 */
+18 −2
Original line number Diff line number Diff line
@@ -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,9 +300,13 @@ 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);
		list_add(&new_ps->head, &pde->sequences);