blob: 40a540a5a72ef00acb29151846ee95693a8a5b9d [file] [log] [blame]
Kyle Swenson8d8f6542021-03-15 11:02:55 -06001/*
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 */
49void 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 */
61void uwb_drp_available(struct uwb_rc *rc, struct uwb_mas_bm *avail)
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 */
74int 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 */
91void 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 */
103void 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;
108 uwb_rsv_handle_drp_avail_change(rc);
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 */
117void 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 */
140static
141unsigned 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 */
201static
202void 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 */
226static
227int 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;
243error:
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 */
271int 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;
284 uwb_rsv_handle_drp_avail_change(rc);
285 mutex_unlock(&rc->rsvs_mutex);
286
287 uwb_rsv_sched_update(rc);
288
289 return 0;
290}