Re: [PATCH v6 4/6] lib/linear_ranges: Add linear_range_get_selector_high_array

From: Amit Sunil Dhamne

Date: Tue Feb 17 2026 - 20:45:55 EST



On 2/16/26 5:58 AM, Matti Vaittinen wrote:
On 14/02/2026 05:12, Amit Sunil Dhamne via B4 Relay wrote:
From: Amit Sunil Dhamne <amitsd@xxxxxxxxxx>

Add a helper function to find the selector for a given value in a linear
range array. The selector should be such that the value it represents
should be higher or equal to the given value.

Signed-off-by: Amit Sunil Dhamne <amitsd@xxxxxxxxxx>
---
  include/linux/linear_range.h |  3 +++
  lib/linear_ranges.c          | 36 ++++++++++++++++++++++++++++++++++++
  2 files changed, 39 insertions(+)

diff --git a/include/linux/linear_range.h b/include/linux/linear_range.h
index 2e4f4c3539c0..0f3037f1a94f 100644
--- a/include/linux/linear_range.h
+++ b/include/linux/linear_range.h
@@ -57,5 +57,8 @@ void linear_range_get_selector_within(const struct linear_range *r,
  int linear_range_get_selector_low_array(const struct linear_range *r,
                      int ranges, unsigned int val,
                      unsigned int *selector, bool *found);
+int linear_range_get_selector_high_array(const struct linear_range *r,
+                     int ranges, unsigned int val,
+                     unsigned int *selector, bool *found);
    #endif
diff --git a/lib/linear_ranges.c b/lib/linear_ranges.c
index a1a7dfa881de..c85583678f6b 100644
--- a/lib/linear_ranges.c
+++ b/lib/linear_ranges.c
@@ -241,6 +241,42 @@ int linear_range_get_selector_high(const struct linear_range *r,
  }
  EXPORT_SYMBOL_GPL(linear_range_get_selector_high);
  +/**
+ * linear_range_get_selector_high_array - return linear range selector for value
+ * @r:        pointer to array of linear ranges where selector is looked from
+ * @ranges:    amount of ranges to scan from array
+ * @val:    value for which the selector is searched
+ * @selector:    address where found selector value is updated
+ * @found:    flag to indicate that given value was in the range
+ *
+ * Scan array of ranges for selector for which range value matches given
+ * input value. Value is matching if it is equal or higher than given value
+ * If given value is found to be in a range scanning is stopped and @found is
+ * set true. If a range with values greater than given value is found
+ * but the range min is being greater than given value, then the range's
+ * lowest selector is updated to @selector and scanning is stopped.

Is there a reason why the scanning is stopped here? What ensures that the rest of the ranges wouldn't contain a better match?

The logic is now different from the linear_range_get_selector_low_array(), and I would like to understand why? It'd be nice if these APIs were 'symmetric' to avoid confusion. Hence, I would like to know rationale behind making them different.


The rationale for this being asymmetric is to find the tightest upper bound for `value` < minimum value across the linear range array.

To better illustrate this with an example. I have 2 entries in the linear range array [ [4, 8], [11, 15] ]. Let's assume I pass a value of "2".

Based on my current approach, the call to get_selector_high() would successfully return with `found`=false and a selector value corresponding to "4".

However, if I continued to search, I would end up the selector corresponding to "11". A selector corresponding to "4" is much closer/tighter than "2".

For values higher than the highest value in any range, this would keep iterating and end up returning an -EINVAL.

For in range values this would work as expected.

This implementation assumes that the linear ranges are provided in sorted order, an assumption that I believe already underlies the existing *_low_array() logic.


Regards,

Amit


+ *
+ * Return: 0 on success, -EINVAL if range array is invalid or does not contain
+ * range with a value greater or equal to given value
+ */
+int linear_range_get_selector_high_array(const struct linear_range *r,
+                     int ranges, unsigned int val,
+                     unsigned int *selector, bool *found)
+{
+    int i;
+    int ret;
+
+    for (i = 0; i < ranges; i++) {
+        ret = linear_range_get_selector_high(&r[i], val, selector,
+                             found);
+        if (!ret)
+            return 0;
+    }
+
+    return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(linear_range_get_selector_high_array);
+
  /**
   * linear_range_get_selector_within - return linear range selector for value
   * @r:        pointer to linear range where selector is looked from