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