* [PATCH] wifi: ath: avoid repeated divisions in DFS PRI detector
@ 2026-07-01 17:04 frank0988
2026-07-01 19:08 ` Jeff Johnson
2026-07-02 3:52 ` [PATCH v2] " Chun-Cheng Chang
0 siblings, 2 replies; 3+ messages in thread
From: frank0988 @ 2026-07-01 17:04 UTC (permalink / raw)
To: Jeff Johnson; +Cc: linux-wireless, linux-kernel, frank0988
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 <frank0988855428@gmail.com>
---
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 <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/reciprocal_div.h>
#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 <linux/list.h>
+#include <linux/reciprocal_div.h>
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
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] wifi: ath: avoid repeated divisions in DFS PRI detector
2026-07-01 17:04 [PATCH] wifi: ath: avoid repeated divisions in DFS PRI detector frank0988
@ 2026-07-01 19:08 ` Jeff Johnson
2026-07-02 3:52 ` [PATCH v2] " Chun-Cheng Chang
1 sibling, 0 replies; 3+ messages in thread
From: Jeff Johnson @ 2026-07-01 19:08 UTC (permalink / raw)
To: frank0988, Jeff Johnson; +Cc: linux-wireless, linux-kernel
On 7/1/2026 10:04 AM, frank0988 wrote:
> 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 <frank0988855428@gmail.com>
You must sign off with a "known identity"
https://www.kernel.org/doc/html/latest/process/submitting-patches.html#developer-s-certificate-of-origin-1-1
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH v2] wifi: ath: avoid repeated divisions in DFS PRI detector
2026-07-01 17:04 [PATCH] wifi: ath: avoid repeated divisions in DFS PRI detector frank0988
2026-07-01 19:08 ` Jeff Johnson
@ 2026-07-02 3:52 ` Chun-Cheng Chang
1 sibling, 0 replies; 3+ messages in thread
From: Chun-Cheng Chang @ 2026-07-02 3:52 UTC (permalink / raw)
To: Jeff Johnson; +Cc: linux-wireless, linux-kernel, Chun-Cheng Chang
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: Chun-Cheng Chang <frank0988855428@gmail.com>
---
Changes in v2:
- Use a known identity for the author and Signed-off-by tags.
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 <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/reciprocal_div.h>
#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 <linux/list.h>
+#include <linux/reciprocal_div.h>
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
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-07-02 3:52 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-01 17:04 [PATCH] wifi: ath: avoid repeated divisions in DFS PRI detector frank0988
2026-07-01 19:08 ` Jeff Johnson
2026-07-02 3:52 ` [PATCH v2] " Chun-Cheng Chang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox