Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * Range add and subtract
4 : : */
5 : : #include <linux/kernel.h>
6 : : #include <linux/init.h>
7 : : #include <linux/sort.h>
8 : : #include <linux/string.h>
9 : : #include <linux/range.h>
10 : :
11 : 0 : int add_range(struct range *range, int az, int nr_range, u64 start, u64 end)
12 : : {
13 [ # # # # ]: 0 : if (start >= end)
14 : : return nr_range;
15 : :
16 : : /* Out of slots: */
17 [ # # # # ]: 0 : if (nr_range >= az)
18 : : return nr_range;
19 : :
20 : 0 : range[nr_range].start = start;
21 : 0 : range[nr_range].end = end;
22 : :
23 : 0 : nr_range++;
24 : :
25 : 0 : return nr_range;
26 : : }
27 : :
28 : 0 : int add_range_with_merge(struct range *range, int az, int nr_range,
29 : : u64 start, u64 end)
30 : : {
31 : : int i;
32 : :
33 [ # # ]: 0 : if (start >= end)
34 : : return nr_range;
35 : :
36 : : /* get new start/end: */
37 [ # # ]: 0 : for (i = 0; i < nr_range; i++) {
38 : : u64 common_start, common_end;
39 : :
40 [ # # ]: 0 : if (!range[i].end)
41 : 0 : continue;
42 : :
43 : 0 : common_start = max(range[i].start, start);
44 : 0 : common_end = min(range[i].end, end);
45 [ # # ]: 0 : if (common_start > common_end)
46 : 0 : continue;
47 : :
48 : : /* new start/end, will add it back at last */
49 : 0 : start = min(range[i].start, start);
50 : 0 : end = max(range[i].end, end);
51 : :
52 : 0 : memmove(&range[i], &range[i + 1],
53 : 0 : (nr_range - (i + 1)) * sizeof(range[i]));
54 : 0 : range[nr_range - 1].start = 0;
55 : 0 : range[nr_range - 1].end = 0;
56 : 0 : nr_range--;
57 : 0 : i--;
58 : : }
59 : :
60 : : /* Need to add it: */
61 : 0 : return add_range(range, az, nr_range, start, end);
62 : : }
63 : :
64 : 0 : void subtract_range(struct range *range, int az, u64 start, u64 end)
65 : : {
66 : : int i, j;
67 : :
68 [ # # ]: 0 : if (start >= end)
69 : 0 : return;
70 : :
71 [ # # ]: 0 : for (j = 0; j < az; j++) {
72 [ # # ]: 0 : if (!range[j].end)
73 : 0 : continue;
74 : :
75 [ # # # # ]: 0 : if (start <= range[j].start && end >= range[j].end) {
76 : 0 : range[j].start = 0;
77 : 0 : range[j].end = 0;
78 : 0 : continue;
79 : : }
80 : :
81 [ # # # # : 0 : if (start <= range[j].start && end < range[j].end &&
# # ]
82 : : range[j].start < end) {
83 : 0 : range[j].start = end;
84 : 0 : continue;
85 : : }
86 : :
87 : :
88 [ # # # # : 0 : if (start > range[j].start && end >= range[j].end &&
# # ]
89 : : range[j].end > start) {
90 : 0 : range[j].end = start;
91 : 0 : continue;
92 : : }
93 : :
94 [ # # # # ]: 0 : if (start > range[j].start && end < range[j].end) {
95 : : /* Find the new spare: */
96 [ # # ]: 0 : for (i = 0; i < az; i++) {
97 [ # # ]: 0 : if (range[i].end == 0)
98 : : break;
99 : : }
100 [ # # ]: 0 : if (i < az) {
101 : 0 : range[i].end = range[j].end;
102 : 0 : range[i].start = end;
103 : : } else {
104 : 0 : pr_err("%s: run out of slot in ranges\n",
105 : : __func__);
106 : : }
107 : 0 : range[j].end = start;
108 : 0 : continue;
109 : : }
110 : : }
111 : : }
112 : :
113 : 0 : static int cmp_range(const void *x1, const void *x2)
114 : : {
115 : : const struct range *r1 = x1;
116 : : const struct range *r2 = x2;
117 : :
118 [ # # ]: 0 : if (r1->start < r2->start)
119 : : return -1;
120 [ # # ]: 0 : if (r1->start > r2->start)
121 : : return 1;
122 : 0 : return 0;
123 : : }
124 : :
125 : 0 : int clean_sort_range(struct range *range, int az)
126 : : {
127 : 0 : int i, j, k = az - 1, nr_range = az;
128 : :
129 [ # # ]: 0 : for (i = 0; i < k; i++) {
130 [ # # ]: 0 : if (range[i].end)
131 : 0 : continue;
132 [ # # ]: 0 : for (j = k; j > i; j--) {
133 [ # # ]: 0 : if (range[j].end) {
134 : 0 : k = j;
135 : 0 : break;
136 : : }
137 : : }
138 [ # # ]: 0 : if (j == i)
139 : : break;
140 : 0 : range[i].start = range[k].start;
141 : 0 : range[i].end = range[k].end;
142 : 0 : range[k].start = 0;
143 : 0 : range[k].end = 0;
144 : 0 : k--;
145 : : }
146 : : /* count it */
147 [ # # ]: 0 : for (i = 0; i < az; i++) {
148 [ # # ]: 0 : if (!range[i].end) {
149 : 0 : nr_range = i;
150 : 0 : break;
151 : : }
152 : : }
153 : :
154 : : /* sort them */
155 : 0 : sort(range, nr_range, sizeof(struct range), cmp_range, NULL);
156 : :
157 : 0 : return nr_range;
158 : : }
159 : :
160 : 0 : void sort_range(struct range *range, int nr_range)
161 : : {
162 : : /* sort them */
163 : 0 : sort(range, nr_range, sizeof(struct range), cmp_range, NULL);
164 : 0 : }
|