]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/uwb/drp-avail.c
Merge git://git.infradead.org/mtd-2.6
[linux-2.6-omap-h63xx.git] / drivers / uwb / drp-avail.c
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  */
61 static void 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  */
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;
108 }
109
110 /**
111  * uwb_drp_avail_ie_update - update the DRP Availability IE
112  * @rc: the radio controller
113  *
114  * avail = global & local
115  */
116 void uwb_drp_avail_ie_update(struct uwb_rc *rc)
117 {
118         struct uwb_mas_bm avail;
119
120         bitmap_and(avail.bm, rc->drp_avail.global, rc->drp_avail.local, UWB_NUM_MAS);
121
122         rc->drp_avail.ie.hdr.element_id = UWB_IE_DRP_AVAILABILITY;
123         rc->drp_avail.ie.hdr.length = UWB_NUM_MAS / 8;
124         uwb_mas_bm_copy_le(rc->drp_avail.ie.bmp, &avail);
125         rc->drp_avail.ie_valid = true;
126 }
127
128 /**
129  * Create an unsigned long from a buffer containing a byte stream.
130  *
131  * @array: pointer to buffer
132  * @itr:   index of buffer from where we start
133  * @len:   the buffer's remaining size may not be exact multiple of
134  *         sizeof(unsigned long), @len is the length of buffer that needs
135  *         to be converted. This will be sizeof(unsigned long) or smaller
136  *         (BUG if not). If it is smaller then we will pad the remaining
137  *         space of the result with zeroes.
138  */
139 static
140 unsigned long get_val(u8 *array, size_t itr, size_t len)
141 {
142         unsigned long val = 0;
143         size_t top = itr + len;
144
145         BUG_ON(len > sizeof(val));
146
147         while (itr < top) {
148                 val <<= 8;
149                 val |= array[top - 1];
150                 top--;
151         }
152         val <<= 8 * (sizeof(val) - len); /* padding */
153         return val;
154 }
155
156 /**
157  * Initialize bitmap from data buffer.
158  *
159  * The bitmap to be converted could come from a IE, for example a
160  * DRP Availability IE.
161  * From ECMA-368 1.0 [16.8.7]: "
162  * octets: 1            1               N * (0 to 32)
163  *         Element ID   Length (=N)     DRP Availability Bitmap
164  *
165  * The DRP Availability Bitmap field is up to 256 bits long, one
166  * bit for each MAS in the superframe, where the least-significant
167  * bit of the field corresponds to the first MAS in the superframe
168  * and successive bits correspond to successive MASs."
169  *
170  * The DRP Availability bitmap is in octets from 0 to 32, so octet
171  * 32 contains bits for MAS 1-8, etc. If the bitmap is smaller than 32
172  * octets, the bits in octets not included at the end of the bitmap are
173  * treated as zero. In this case (when the bitmap is smaller than 32
174  * octets) the MAS represented range from MAS 1 to MAS (size of bitmap)
175  * with the last octet still containing bits for MAS 1-8, etc.
176  *
177  * For example:
178  * F00F0102 03040506 0708090A 0B0C0D0E 0F010203
179  * ^^^^
180  * ||||
181  * ||||
182  * |||\LSB of byte is MAS 9
183  * ||\MSB of byte is MAS 16
184  * |\LSB of first byte is MAS 1
185  * \ MSB of byte is MAS 8
186  *
187  * An example of this encoding can be found in ECMA-368 Annex-D [Table D.11]
188  *
189  * The resulting bitmap will have the following mapping:
190  *      bit position 0 == MAS 1
191  *      bit position 1 == MAS 2
192  *      ...
193  *      bit position (UWB_NUM_MAS - 1) == MAS UWB_NUM_MAS
194  *
195  * @bmp_itr:    pointer to bitmap (can be declared with DECLARE_BITMAP)
196  * @buffer:     pointer to buffer containing bitmap data in big endian
197  *              format (MSB first)
198  * @buffer_size:number of bytes with which bitmap should be initialized
199  */
200 static
201 void buffer_to_bmp(unsigned long *bmp_itr, void *_buffer,
202                    size_t buffer_size)
203 {
204         u8 *buffer = _buffer;
205         size_t itr, len;
206         unsigned long val;
207
208         itr = 0;
209         while (itr < buffer_size) {
210                 len = buffer_size - itr >= sizeof(val) ?
211                         sizeof(val) : buffer_size - itr;
212                 val = get_val(buffer, itr, len);
213                 bmp_itr[itr / sizeof(val)] = val;
214                 itr += sizeof(val);
215         }
216 }
217
218
219 /**
220  * Extract DRP Availability bitmap from the notification.
221  *
222  * The notification that comes in contains a bitmap of (UWB_NUM_MAS / 8) bytes
223  * We convert that to our internal representation.
224  */
225 static
226 int uwbd_evt_get_drp_avail(struct uwb_event *evt, unsigned long *bmp)
227 {
228         struct device *dev = &evt->rc->uwb_dev.dev;
229         struct uwb_rc_evt_drp_avail *drp_evt;
230         int result = -EINVAL;
231
232         /* Is there enough data to decode the event? */
233         if (evt->notif.size < sizeof(*drp_evt)) {
234                 dev_err(dev, "DRP Availability Change: Not enough "
235                         "data to decode event [%zu bytes, %zu "
236                         "needed]\n", evt->notif.size, sizeof(*drp_evt));
237                 goto error;
238         }
239         drp_evt = container_of(evt->notif.rceb, struct uwb_rc_evt_drp_avail, rceb);
240         buffer_to_bmp(bmp, drp_evt->bmp, UWB_NUM_MAS/8);
241         result = 0;
242 error:
243         return result;
244 }
245
246
247 /**
248  * Process an incoming DRP Availability notification.
249  *
250  * @evt:        Event information (packs the actual event data, which
251  *              radio controller it came to, etc).
252  *
253  * @returns:    0 on success (so uwbd() frees the event buffer), < 0
254  *              on error.
255  *
256  * According to ECMA-368 1.0 [16.8.7], bits set to ONE indicate that
257  * the MAS slot is available, bits set to ZERO indicate that the slot
258  * is busy.
259  *
260  * So we clear available slots, we set used slots :)
261  *
262  * The notification only marks non-availability based on the BP and
263  * received DRP IEs that are not for this radio controller.  A copy of
264  * this bitmap is needed to generate the real availability (which
265  * includes local and pending reservations).
266  *
267  * The DRP Availability IE that this radio controller emits will need
268  * to be updated.
269  */
270 int uwbd_evt_handle_rc_drp_avail(struct uwb_event *evt)
271 {
272         int result;
273         struct uwb_rc *rc = evt->rc;
274         DECLARE_BITMAP(bmp, UWB_NUM_MAS);
275
276         result = uwbd_evt_get_drp_avail(evt, bmp);
277         if (result < 0)
278                 return result;
279
280         mutex_lock(&rc->rsvs_mutex);
281         bitmap_copy(rc->drp_avail.global, bmp, UWB_NUM_MAS);
282         rc->drp_avail.ie_valid = false;
283         mutex_unlock(&rc->rsvs_mutex);
284
285         uwb_rsv_sched_update(rc);
286
287         return 0;
288 }