Commit | Line | Data |
---|---|---|
8cc13a09 DV |
1 | /* |
2 | * Ultra Wide Band | |
3 | * DRP availability management | |
4 | * | |
5 | * Copyright (C) 2005-2006 Intel Corporation | |
6 | * Reinette Chatre <reinette.chatre@intel.com> | |
7 | * Copyright (C) 2008 Cambridge Silicon Radio Ltd. | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU General Public License version | |
11 | * 2 as published by the Free Software Foundation. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
20 | * | |
21 | * | |
22 | * Manage DRP Availability (the MAS available for DRP | |
23 | * reservations). Thus: | |
24 | * | |
25 | * - Handle DRP Availability Change notifications | |
26 | * | |
27 | * - Allow the reservation manager to indicate MAS reserved/released | |
28 | * by local (owned by/targeted at the radio controller) | |
29 | * reservations. | |
30 | * | |
31 | * - Based on the two sources above, generate a DRP Availability IE to | |
32 | * be included in the beacon. | |
33 | * | |
34 | * See also the documentation for struct uwb_drp_avail. | |
35 | */ | |
36 | ||
37 | #include <linux/errno.h> | |
38 | #include <linux/module.h> | |
39 | #include <linux/device.h> | |
40 | #include <linux/bitmap.h> | |
41 | #include "uwb-internal.h" | |
42 | ||
43 | /** | |
44 | * uwb_drp_avail_init - initialize an RC's MAS availability | |
45 | * | |
46 | * All MAS are available initially. The RC will inform use which | |
47 | * slots are used for the BP (it may change in size). | |
48 | */ | |
49 | void uwb_drp_avail_init(struct uwb_rc *rc) | |
50 | { | |
51 | bitmap_fill(rc->drp_avail.global, UWB_NUM_MAS); | |
52 | bitmap_fill(rc->drp_avail.local, UWB_NUM_MAS); | |
53 | bitmap_fill(rc->drp_avail.pending, UWB_NUM_MAS); | |
54 | } | |
55 | ||
56 | /* | |
57 | * Determine MAS available for new local reservations. | |
58 | * | |
59 | * avail = global & local & pending | |
60 | */ | |
5b37717a | 61 | void uwb_drp_available(struct uwb_rc *rc, struct uwb_mas_bm *avail) |
8cc13a09 DV |
62 | { |
63 | bitmap_and(avail->bm, rc->drp_avail.global, rc->drp_avail.local, UWB_NUM_MAS); | |
64 | bitmap_and(avail->bm, avail->bm, rc->drp_avail.pending, UWB_NUM_MAS); | |
65 | } | |
66 | ||
67 | /** | |
68 | * uwb_drp_avail_reserve_pending - reserve MAS for a new reservation | |
69 | * @rc: the radio controller | |
70 | * @mas: the MAS to reserve | |
71 | * | |
72 | * Returns 0 on success, or -EBUSY if the MAS requested aren't available. | |
73 | */ | |
74 | int uwb_drp_avail_reserve_pending(struct uwb_rc *rc, struct uwb_mas_bm *mas) | |
75 | { | |
76 | struct uwb_mas_bm avail; | |
77 | ||
78 | uwb_drp_available(rc, &avail); | |
79 | if (!bitmap_subset(mas->bm, avail.bm, UWB_NUM_MAS)) | |
80 | return -EBUSY; | |
81 | ||
82 | bitmap_andnot(rc->drp_avail.pending, rc->drp_avail.pending, mas->bm, UWB_NUM_MAS); | |
83 | return 0; | |
84 | } | |
85 | ||
86 | /** | |
87 | * uwb_drp_avail_reserve - reserve MAS for an established reservation | |
88 | * @rc: the radio controller | |
89 | * @mas: the MAS to reserve | |
90 | */ | |
91 | void uwb_drp_avail_reserve(struct uwb_rc *rc, struct uwb_mas_bm *mas) | |
92 | { | |
93 | bitmap_or(rc->drp_avail.pending, rc->drp_avail.pending, mas->bm, UWB_NUM_MAS); | |
94 | bitmap_andnot(rc->drp_avail.local, rc->drp_avail.local, mas->bm, UWB_NUM_MAS); | |
95 | rc->drp_avail.ie_valid = false; | |
96 | } | |
97 | ||
98 | /** | |
99 | * uwb_drp_avail_release - release MAS from a pending or established reservation | |
100 | * @rc: the radio controller | |
101 | * @mas: the MAS to release | |
102 | */ | |
103 | void uwb_drp_avail_release(struct uwb_rc *rc, struct uwb_mas_bm *mas) | |
104 | { | |
105 | bitmap_or(rc->drp_avail.local, rc->drp_avail.local, mas->bm, UWB_NUM_MAS); | |
106 | bitmap_or(rc->drp_avail.pending, rc->drp_avail.pending, mas->bm, UWB_NUM_MAS); | |
107 | rc->drp_avail.ie_valid = false; | |
5b37717a | 108 | uwb_rsv_handle_drp_avail_change(rc); |
8cc13a09 DV |
109 | } |
110 | ||
111 | /** | |
112 | * uwb_drp_avail_ie_update - update the DRP Availability IE | |
113 | * @rc: the radio controller | |
114 | * | |
115 | * avail = global & local | |
116 | */ | |
117 | void uwb_drp_avail_ie_update(struct uwb_rc *rc) | |
118 | { | |
119 | struct uwb_mas_bm avail; | |
120 | ||
121 | bitmap_and(avail.bm, rc->drp_avail.global, rc->drp_avail.local, UWB_NUM_MAS); | |
122 | ||
123 | rc->drp_avail.ie.hdr.element_id = UWB_IE_DRP_AVAILABILITY; | |
124 | rc->drp_avail.ie.hdr.length = UWB_NUM_MAS / 8; | |
125 | uwb_mas_bm_copy_le(rc->drp_avail.ie.bmp, &avail); | |
126 | rc->drp_avail.ie_valid = true; | |
127 | } | |
128 | ||
129 | /** | |
130 | * Create an unsigned long from a buffer containing a byte stream. | |
131 | * | |
132 | * @array: pointer to buffer | |
133 | * @itr: index of buffer from where we start | |
134 | * @len: the buffer's remaining size may not be exact multiple of | |
135 | * sizeof(unsigned long), @len is the length of buffer that needs | |
136 | * to be converted. This will be sizeof(unsigned long) or smaller | |
137 | * (BUG if not). If it is smaller then we will pad the remaining | |
138 | * space of the result with zeroes. | |
139 | */ | |
140 | static | |
141 | unsigned long get_val(u8 *array, size_t itr, size_t len) | |
142 | { | |
143 | unsigned long val = 0; | |
144 | size_t top = itr + len; | |
145 | ||
146 | BUG_ON(len > sizeof(val)); | |
147 | ||
148 | while (itr < top) { | |
149 | val <<= 8; | |
150 | val |= array[top - 1]; | |
151 | top--; | |
152 | } | |
153 | val <<= 8 * (sizeof(val) - len); /* padding */ | |
154 | return val; | |
155 | } | |
156 | ||
157 | /** | |
158 | * Initialize bitmap from data buffer. | |
159 | * | |
160 | * The bitmap to be converted could come from a IE, for example a | |
161 | * DRP Availability IE. | |
162 | * From ECMA-368 1.0 [16.8.7]: " | |
163 | * octets: 1 1 N * (0 to 32) | |
164 | * Element ID Length (=N) DRP Availability Bitmap | |
165 | * | |
166 | * The DRP Availability Bitmap field is up to 256 bits long, one | |
167 | * bit for each MAS in the superframe, where the least-significant | |
168 | * bit of the field corresponds to the first MAS in the superframe | |
169 | * and successive bits correspond to successive MASs." | |
170 | * | |
171 | * The DRP Availability bitmap is in octets from 0 to 32, so octet | |
172 | * 32 contains bits for MAS 1-8, etc. If the bitmap is smaller than 32 | |
173 | * octets, the bits in octets not included at the end of the bitmap are | |
174 | * treated as zero. In this case (when the bitmap is smaller than 32 | |
175 | * octets) the MAS represented range from MAS 1 to MAS (size of bitmap) | |
176 | * with the last octet still containing bits for MAS 1-8, etc. | |
177 | * | |
178 | * For example: | |
179 | * F00F0102 03040506 0708090A 0B0C0D0E 0F010203 | |
180 | * ^^^^ | |
181 | * |||| | |
182 | * |||| | |
183 | * |||\LSB of byte is MAS 9 | |
184 | * ||\MSB of byte is MAS 16 | |
185 | * |\LSB of first byte is MAS 1 | |
186 | * \ MSB of byte is MAS 8 | |
187 | * | |
188 | * An example of this encoding can be found in ECMA-368 Annex-D [Table D.11] | |
189 | * | |
190 | * The resulting bitmap will have the following mapping: | |
191 | * bit position 0 == MAS 1 | |
192 | * bit position 1 == MAS 2 | |
193 | * ... | |
194 | * bit position (UWB_NUM_MAS - 1) == MAS UWB_NUM_MAS | |
195 | * | |
196 | * @bmp_itr: pointer to bitmap (can be declared with DECLARE_BITMAP) | |
197 | * @buffer: pointer to buffer containing bitmap data in big endian | |
198 | * format (MSB first) | |
199 | * @buffer_size:number of bytes with which bitmap should be initialized | |
200 | */ | |
201 | static | |
202 | void buffer_to_bmp(unsigned long *bmp_itr, void *_buffer, | |
203 | size_t buffer_size) | |
204 | { | |
205 | u8 *buffer = _buffer; | |
206 | size_t itr, len; | |
207 | unsigned long val; | |
208 | ||
209 | itr = 0; | |
210 | while (itr < buffer_size) { | |
211 | len = buffer_size - itr >= sizeof(val) ? | |
212 | sizeof(val) : buffer_size - itr; | |
213 | val = get_val(buffer, itr, len); | |
214 | bmp_itr[itr / sizeof(val)] = val; | |
215 | itr += sizeof(val); | |
216 | } | |
217 | } | |
218 | ||
219 | ||
220 | /** | |
221 | * Extract DRP Availability bitmap from the notification. | |
222 | * | |
223 | * The notification that comes in contains a bitmap of (UWB_NUM_MAS / 8) bytes | |
224 | * We convert that to our internal representation. | |
225 | */ | |
226 | static | |
227 | int uwbd_evt_get_drp_avail(struct uwb_event *evt, unsigned long *bmp) | |
228 | { | |
229 | struct device *dev = &evt->rc->uwb_dev.dev; | |
230 | struct uwb_rc_evt_drp_avail *drp_evt; | |
231 | int result = -EINVAL; | |
232 | ||
233 | /* Is there enough data to decode the event? */ | |
234 | if (evt->notif.size < sizeof(*drp_evt)) { | |
235 | dev_err(dev, "DRP Availability Change: Not enough " | |
236 | "data to decode event [%zu bytes, %zu " | |
237 | "needed]\n", evt->notif.size, sizeof(*drp_evt)); | |
238 | goto error; | |
239 | } | |
240 | drp_evt = container_of(evt->notif.rceb, struct uwb_rc_evt_drp_avail, rceb); | |
241 | buffer_to_bmp(bmp, drp_evt->bmp, UWB_NUM_MAS/8); | |
242 | result = 0; | |
243 | error: | |
244 | return result; | |
245 | } | |
246 | ||
247 | ||
248 | /** | |
249 | * Process an incoming DRP Availability notification. | |
250 | * | |
251 | * @evt: Event information (packs the actual event data, which | |
252 | * radio controller it came to, etc). | |
253 | * | |
254 | * @returns: 0 on success (so uwbd() frees the event buffer), < 0 | |
255 | * on error. | |
256 | * | |
257 | * According to ECMA-368 1.0 [16.8.7], bits set to ONE indicate that | |
258 | * the MAS slot is available, bits set to ZERO indicate that the slot | |
259 | * is busy. | |
260 | * | |
261 | * So we clear available slots, we set used slots :) | |
262 | * | |
263 | * The notification only marks non-availability based on the BP and | |
264 | * received DRP IEs that are not for this radio controller. A copy of | |
265 | * this bitmap is needed to generate the real availability (which | |
266 | * includes local and pending reservations). | |
267 | * | |
268 | * The DRP Availability IE that this radio controller emits will need | |
269 | * to be updated. | |
270 | */ | |
271 | int uwbd_evt_handle_rc_drp_avail(struct uwb_event *evt) | |
272 | { | |
273 | int result; | |
274 | struct uwb_rc *rc = evt->rc; | |
275 | DECLARE_BITMAP(bmp, UWB_NUM_MAS); | |
276 | ||
277 | result = uwbd_evt_get_drp_avail(evt, bmp); | |
278 | if (result < 0) | |
279 | return result; | |
280 | ||
281 | mutex_lock(&rc->rsvs_mutex); | |
282 | bitmap_copy(rc->drp_avail.global, bmp, UWB_NUM_MAS); | |
283 | rc->drp_avail.ie_valid = false; | |
5b37717a | 284 | uwb_rsv_handle_drp_avail_change(rc); |
8cc13a09 DV |
285 | mutex_unlock(&rc->rsvs_mutex); |
286 | ||
287 | uwb_rsv_sched_update(rc); | |
288 | ||
289 | return 0; | |
290 | } |