~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/lib/linear_ranges.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * helpers to map values in a linear range to range index
  4  *
  5  * Original idea borrowed from regulator framework
  6  *
  7  * It might be useful if we could support also inversely proportional ranges?
  8  * Copyright 2020 ROHM Semiconductors
  9  */
 10 
 11 #include <linux/errno.h>
 12 #include <linux/export.h>
 13 #include <linux/kernel.h>
 14 #include <linux/linear_range.h>
 15 #include <linux/module.h>
 16 
 17 /**
 18  * linear_range_values_in_range - return the amount of values in a range
 19  * @r:          pointer to linear range where values are counted
 20  *
 21  * Compute the amount of values in range pointed by @r. Note, values can
 22  * be all equal - range with selectors 0,...,2 with step 0 still contains
 23  * 3 values even though they are all equal.
 24  *
 25  * Return: the amount of values in range pointed by @r
 26  */
 27 unsigned int linear_range_values_in_range(const struct linear_range *r)
 28 {
 29         if (!r)
 30                 return 0;
 31         return r->max_sel - r->min_sel + 1;
 32 }
 33 EXPORT_SYMBOL_GPL(linear_range_values_in_range);
 34 
 35 /**
 36  * linear_range_values_in_range_array - return the amount of values in ranges
 37  * @r:          pointer to array of linear ranges where values are counted
 38  * @ranges:     amount of ranges we include in computation.
 39  *
 40  * Compute the amount of values in ranges pointed by @r. Note, values can
 41  * be all equal - range with selectors 0,...,2 with step 0 still contains
 42  * 3 values even though they are all equal.
 43  *
 44  * Return: the amount of values in first @ranges ranges pointed by @r
 45  */
 46 unsigned int linear_range_values_in_range_array(const struct linear_range *r,
 47                                                 int ranges)
 48 {
 49         int i, values_in_range = 0;
 50 
 51         for (i = 0; i < ranges; i++) {
 52                 int values;
 53 
 54                 values = linear_range_values_in_range(&r[i]);
 55                 if (!values)
 56                         return values;
 57 
 58                 values_in_range += values;
 59         }
 60         return values_in_range;
 61 }
 62 EXPORT_SYMBOL_GPL(linear_range_values_in_range_array);
 63 
 64 /**
 65  * linear_range_get_max_value - return the largest value in a range
 66  * @r:          pointer to linear range where value is looked from
 67  *
 68  * Return: the largest value in the given range
 69  */
 70 unsigned int linear_range_get_max_value(const struct linear_range *r)
 71 {
 72         return r->min + (r->max_sel - r->min_sel) * r->step;
 73 }
 74 EXPORT_SYMBOL_GPL(linear_range_get_max_value);
 75 
 76 /**
 77  * linear_range_get_value - fetch a value from given range
 78  * @r:          pointer to linear range where value is looked from
 79  * @selector:   selector for which the value is searched
 80  * @val:        address where found value is updated
 81  *
 82  * Search given ranges for value which matches given selector.
 83  *
 84  * Return: 0 on success, -EINVAL given selector is not found from any of the
 85  * ranges.
 86  */
 87 int linear_range_get_value(const struct linear_range *r, unsigned int selector,
 88                            unsigned int *val)
 89 {
 90         if (r->min_sel > selector || r->max_sel < selector)
 91                 return -EINVAL;
 92 
 93         *val = r->min + (selector - r->min_sel) * r->step;
 94 
 95         return 0;
 96 }
 97 EXPORT_SYMBOL_GPL(linear_range_get_value);
 98 
 99 /**
100  * linear_range_get_value_array - fetch a value from array of ranges
101  * @r:          pointer to array of linear ranges where value is looked from
102  * @ranges:     amount of ranges in an array
103  * @selector:   selector for which the value is searched
104  * @val:        address where found value is updated
105  *
106  * Search through an array of ranges for value which matches given selector.
107  *
108  * Return: 0 on success, -EINVAL given selector is not found from any of the
109  * ranges.
110  */
111 int linear_range_get_value_array(const struct linear_range *r, int ranges,
112                                  unsigned int selector, unsigned int *val)
113 {
114         int i;
115 
116         for (i = 0; i < ranges; i++)
117                 if (r[i].min_sel <= selector && r[i].max_sel >= selector)
118                         return linear_range_get_value(&r[i], selector, val);
119 
120         return -EINVAL;
121 }
122 EXPORT_SYMBOL_GPL(linear_range_get_value_array);
123 
124 /**
125  * linear_range_get_selector_low - return linear range selector for value
126  * @r:          pointer to linear range where selector is looked from
127  * @val:        value for which the selector is searched
128  * @selector:   address where found selector value is updated
129  * @found:      flag to indicate that given value was in the range
130  *
131  * Return selector for which range value is closest match for given
132  * input value. Value is matching if it is equal or smaller than given
133  * value. If given value is in the range, then @found is set true.
134  *
135  * Return: 0 on success, -EINVAL if range is invalid or does not contain
136  * value smaller or equal to given value
137  */
138 int linear_range_get_selector_low(const struct linear_range *r,
139                                   unsigned int val, unsigned int *selector,
140                                   bool *found)
141 {
142         *found = false;
143 
144         if (r->min > val)
145                 return -EINVAL;
146 
147         if (linear_range_get_max_value(r) < val) {
148                 *selector = r->max_sel;
149                 return 0;
150         }
151 
152         *found = true;
153 
154         if (r->step == 0)
155                 *selector = r->min_sel;
156         else
157                 *selector = (val - r->min) / r->step + r->min_sel;
158 
159         return 0;
160 }
161 EXPORT_SYMBOL_GPL(linear_range_get_selector_low);
162 
163 /**
164  * linear_range_get_selector_low_array - return linear range selector for value
165  * @r:          pointer to array of linear ranges where selector is looked from
166  * @ranges:     amount of ranges to scan from array
167  * @val:        value for which the selector is searched
168  * @selector:   address where found selector value is updated
169  * @found:      flag to indicate that given value was in the range
170  *
171  * Scan array of ranges for selector for which range value matches given
172  * input value. Value is matching if it is equal or smaller than given
173  * value. If given value is found to be in a range scanning is stopped and
174  * @found is set true. If a range with values smaller than given value is found
175  * but the range max is being smaller than given value, then the range's
176  * biggest selector is updated to @selector but scanning ranges is continued
177  * and @found is set to false.
178  *
179  * Return: 0 on success, -EINVAL if range array is invalid or does not contain
180  * range with a value smaller or equal to given value
181  */
182 int linear_range_get_selector_low_array(const struct linear_range *r,
183                                         int ranges, unsigned int val,
184                                         unsigned int *selector, bool *found)
185 {
186         int i;
187         int ret = -EINVAL;
188 
189         for (i = 0; i < ranges; i++) {
190                 int tmpret;
191 
192                 tmpret = linear_range_get_selector_low(&r[i], val, selector,
193                                                        found);
194                 if (!tmpret)
195                         ret = 0;
196 
197                 if (*found)
198                         break;
199         }
200 
201         return ret;
202 }
203 EXPORT_SYMBOL_GPL(linear_range_get_selector_low_array);
204 
205 /**
206  * linear_range_get_selector_high - return linear range selector for value
207  * @r:          pointer to linear range where selector is looked from
208  * @val:        value for which the selector is searched
209  * @selector:   address where found selector value is updated
210  * @found:      flag to indicate that given value was in the range
211  *
212  * Return selector for which range value is closest match for given
213  * input value. Value is matching if it is equal or higher than given
214  * value. If given value is in the range, then @found is set true.
215  *
216  * Return: 0 on success, -EINVAL if range is invalid or does not contain
217  * value greater or equal to given value
218  */
219 int linear_range_get_selector_high(const struct linear_range *r,
220                                    unsigned int val, unsigned int *selector,
221                                    bool *found)
222 {
223         *found = false;
224 
225         if (linear_range_get_max_value(r) < val)
226                 return -EINVAL;
227 
228         if (r->min > val) {
229                 *selector = r->min_sel;
230                 return 0;
231         }
232 
233         *found = true;
234 
235         if (r->step == 0)
236                 *selector = r->max_sel;
237         else
238                 *selector = DIV_ROUND_UP(val - r->min, r->step) + r->min_sel;
239 
240         return 0;
241 }
242 EXPORT_SYMBOL_GPL(linear_range_get_selector_high);
243 
244 /**
245  * linear_range_get_selector_within - return linear range selector for value
246  * @r:          pointer to linear range where selector is looked from
247  * @val:        value for which the selector is searched
248  * @selector:   address where found selector value is updated
249  *
250  * Return selector for which range value is closest match for given
251  * input value. Value is matching if it is equal or lower than given
252  * value. But return maximum selector if given value is higher than
253  * maximum value.
254  */
255 void linear_range_get_selector_within(const struct linear_range *r,
256                                       unsigned int val, unsigned int *selector)
257 {
258         if (r->min > val) {
259                 *selector = r->min_sel;
260                 return;
261         }
262 
263         if (linear_range_get_max_value(r) < val) {
264                 *selector = r->max_sel;
265                 return;
266         }
267 
268         if (r->step == 0)
269                 *selector = r->min_sel;
270         else
271                 *selector = (val - r->min) / r->step + r->min_sel;
272 }
273 EXPORT_SYMBOL_GPL(linear_range_get_selector_within);
274 
275 MODULE_DESCRIPTION("linear-ranges helper");
276 MODULE_LICENSE("GPL");
277 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php