pde_get_multiple() is called repeatedly with the same PRI (Pulse Repetition Interval) value while validating candidate and existing PRI sequences. Cache the reciprocal value for each sequence structure and leverage reciprocal_divide() in the hot path. This keeps the existing matching logic and tolerance checks intact while replacing expensive hardware integer divisions with low-cost multiply-and-shift operations. Testing with a userspace model of the same detector logic demonstrated identical detector states and outputs across 100 verification traces. To eliminate memory allocator noise, an isolated micro-benchmark using a static object pool showed that the reciprocal variant reduces CPU cycles by approximately 3.4%. Signed-off-by: frank0988 --- drivers/net/wireless/ath/dfs_pri_detector.c | 14 +++++++++++--- drivers/net/wireless/ath/dfs_pri_detector.h | 3 +++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/dfs_pri_detector.c b/drivers/net/wireless/ath/dfs_pri_detector.c index 388f9d1913bd..520fd1567a0b 100644 --- a/drivers/net/wireless/ath/dfs_pri_detector.c +++ b/drivers/net/wireless/ath/dfs_pri_detector.c @@ -16,6 +16,7 @@ #include #include +#include #include "ath.h" #include "dfs_pattern_detector.h" @@ -41,7 +42,9 @@ struct pulse_elem { * pde_get_multiple() - get number of multiples considering a given tolerance * Return value: factor if abs(val - factor*fraction) <= tolerance, 0 otherwise */ -static u32 pde_get_multiple(u32 val, u32 fraction, u32 tolerance) +static u32 pde_get_multiple(u32 val, u32 fraction, + struct reciprocal_value fraction_recip, + u32 tolerance) { u32 remainder; u32 factor; @@ -56,8 +59,8 @@ static u32 pde_get_multiple(u32 val, u32 fraction, u32 tolerance) /* val and fraction are within tolerance */ return 1; - factor = val / fraction; - remainder = val % fraction; + factor = reciprocal_divide(val, fraction_recip); + remainder = val - factor * fraction; if (remainder > tolerance) { /* no exact match */ if ((fraction - remainder) <= tolerance) @@ -247,6 +250,9 @@ static bool pseq_handler_create_sequences(struct pri_detector *pde, ps.last_ts = ts; ps.pri = GET_PRI_TO_USE(pde->rs->pri_min, pde->rs->pri_max, ts - p->ts); + ps.pri_recip = (struct reciprocal_value){}; + if (ps.pri) + ps.pri_recip = reciprocal_value(ps.pri); ps.dur = ps.pri * (pde->rs->ppb - 1) + 2 * pde->rs->max_pri_tolerance; @@ -261,6 +267,7 @@ static bool pseq_handler_create_sequences(struct pri_detector *pde, break; /* check if pulse match (multi)PRI */ factor = pde_get_multiple(ps.last_ts - p2->ts, ps.pri, + ps.pri_recip, pde->rs->max_pri_tolerance); if (factor > 0) { ps.count++; @@ -318,6 +325,7 @@ pseq_handler_add_to_existing_seqs(struct pri_detector *pde, u64 ts) delta_ts = ts - ps->last_ts; factor = pde_get_multiple(delta_ts, ps->pri, + ps->pri_recip, pde->rs->max_pri_tolerance); if (factor > 0) { ps->last_ts = ts; diff --git a/drivers/net/wireless/ath/dfs_pri_detector.h b/drivers/net/wireless/ath/dfs_pri_detector.h index 86339f2b4d3a..c519466cff8b 100644 --- a/drivers/net/wireless/ath/dfs_pri_detector.h +++ b/drivers/net/wireless/ath/dfs_pri_detector.h @@ -18,6 +18,7 @@ #define DFS_PRI_DETECTOR_H #include +#include extern struct ath_dfs_pool_stats global_dfs_pool_stats; @@ -25,6 +26,7 @@ extern struct ath_dfs_pool_stats global_dfs_pool_stats; * struct pri_sequence - sequence of pulses matching one PRI * @head: list_head * @pri: pulse repetition interval (PRI) in usecs + * @pri_recip: cached reciprocal value for PRI divisions * @dur: duration of sequence in usecs * @count: number of pulses in this sequence * @count_falses: number of not matching pulses in this sequence @@ -35,6 +37,7 @@ extern struct ath_dfs_pool_stats global_dfs_pool_stats; struct pri_sequence { struct list_head head; u32 pri; + struct reciprocal_value pri_recip; u32 dur; u32 count; u32 count_falses; -- 2.53.0